From 0b7dad269647824cad84226d021d7ddab1132b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Tue, 4 Feb 2025 00:12:15 -0300 Subject: [PATCH] Update breakpoints line position if document is edited (added/removed lines). --- include/eepp/ui/doc/textdocument.hpp | 7 ++- .../ecode/plugins/debugger/debuggerplugin.cpp | 47 +++++++++++++++++++ .../ecode/plugins/debugger/debuggerplugin.hpp | 35 ++++++++++++++ .../debugger/models/breakpointsmodel.cpp | 18 +++++++ .../debugger/models/breakpointsmodel.hpp | 2 + .../ecode/plugins/xmltools/xmltoolsplugin.hpp | 16 +++---- 6 files changed, 116 insertions(+), 9 deletions(-) diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index abd3e0842..91bee978e 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -91,15 +91,20 @@ class EE_API TextDocument { virtual void onDocumentClosed( TextDocument* ) = 0; virtual void onDocumentDirtyOnFileSystem( TextDocument* ) = 0; virtual void onDocumentMoved( TextDocument* ) = 0; + virtual void onDocumentReset( TextDocument* ) = 0; + virtual void onDocumentReloaded( TextDocument* doc ) { onDocumentClosed( doc ); onDocumentLoaded( doc ); } - virtual void onDocumentReset( TextDocument* ) = 0; + virtual void onDocumentSyntaxDefinitionChange( const SyntaxDefinition& ) {} + virtual void onDocumentLineMove( const Int64& /*fromLine*/, const Int64& /*toLine*/, const Int64& /*numLines*/ ) {} + virtual TextRange getVisibleRange() const { return {}; }; + virtual void onFoldRegionsUpdated( size_t /*oldCount*/, size_t /*newCount*/ ) {} }; diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index f09de0fc3..5ba5f8083 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -80,6 +80,12 @@ DebuggerPlugin::~DebuggerPlugin() { waitUntilLoaded(); mShuttingDown = true; + { + Lock l( mClientsMutex ); + for ( const auto& client : mClients ) + client.first->unregisterClient( client.second.get() ); + } + if ( mSidePanel && mTab ) { if ( Engine::isRunninMainThread() ) mSidePanel->removeTab( mTab ); @@ -1311,6 +1317,16 @@ void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) { if ( mTab ) mTab->setTabSelected(); } ); + + Lock l( mClientsMutex ); + mClients[doc] = std::make_unique( this, doc ); + doc->registerClient( mClients[doc].get() ); +} + +void DebuggerPlugin::onUnregisterDocument( TextDocument* doc ) { + Lock l( mClientsMutex ); + doc->unregisterClient( mClients[doc].get() ); + mClients.erase( doc ); } void DebuggerPlugin::onRegisterEditor( UICodeEditor* editor ) { @@ -2214,4 +2230,35 @@ bool DebuggerPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position return true; } +void DebuggerPlugin::onDocumentLineMove( TextDocument* doc, const Int64& fromLine, + const Int64& toLine, const Int64& numLines ) { + Lock l( mBreakpointsMutex ); + + auto& breakpoints = mBreakpoints[doc->getFilePath()]; + + if ( breakpoints.empty() ) + return; + + std::vector bpToModify; + + for ( auto& bp : breakpoints ) { + // bp line numbers start at 1 + if ( bp.line - 1 >= fromLine ) { + bpToModify.push_back( bp ); + break; + } + } + + for ( const auto& bp : bpToModify ) + breakpoints.erase( bp ); + + for ( auto&& bp : bpToModify ) { + bp.line += numLines; + breakpoints.insert( std::move( bp ) ); + } + + if ( mBreakpointsModel ) + mBreakpointsModel->move( doc->getFilePath(), fromLine, toLine, numLines ); +} + } // namespace ecode diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp index 8a724c405..8b634aa99 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp @@ -129,6 +129,37 @@ class DebuggerPlugin : public PluginBase { std::string mCurDebugger; std::string mCurConfiguration; + class DebuggerPluginClient : public TextDocument::Client { + public: + explicit DebuggerPluginClient( DebuggerPlugin* parent, TextDocument* doc ) : + mDoc( doc ), mParent( parent ) {} + + virtual void onDocumentTextChanged( const DocumentContentChange& ) {} + virtual void onDocumentUndoRedo( const TextDocument::UndoRedo& ) {} + virtual void onDocumentCursorChange( const TextPosition& ) {} + virtual void onDocumentSelectionChange( const TextRange& ) {} + virtual void onDocumentLineCountChange( const size_t&, const size_t& ) {} + virtual void onDocumentLineChanged( const Int64& ) {} + virtual void onDocumentSaved( TextDocument* ) {} + virtual void onDocumentClosed( TextDocument* doc ) { onDocumentReset( doc ); } + virtual void onDocumentDirtyOnFileSystem( TextDocument* ) {} + virtual void onDocumentMoved( TextDocument* ) {} + virtual void onDocumentReset( TextDocument* ) {} + + virtual void onDocumentLineMove( const Int64& fromLine, const Int64& toLine, + const Int64& numLines ) { + mParent->onDocumentLineMove( mDoc, fromLine, toLine, numLines ); + } + + protected: + TextDocument* mDoc{ nullptr }; + DebuggerPlugin* mParent{ nullptr }; + }; + + using ClientsMap = std::unordered_map>; + ClientsMap mClients; + Mutex mClientsMutex; + DebuggerPlugin( PluginManager* pluginManager, bool sync ); void load( PluginManager* pluginManager ); @@ -240,6 +271,10 @@ class DebuggerPlugin : public PluginBase { bool resume( int threadId, bool singleThread = false ); + virtual void onUnregisterDocument( TextDocument* doc ) override; + + void onDocumentLineMove( TextDocument* doc, const Int64& fromLine, const Int64& toLine, + const Int64& numLines ); }; } // namespace ecode diff --git a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp index 1d5e7c2b5..4fcb97063 100644 --- a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp +++ b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.cpp @@ -106,6 +106,24 @@ void BreakpointsModel::enable( const std::string& filePath, } } +void BreakpointsModel::move( const std::string& doc, Int64 fromLine, Int64 toLine, + Int64 numLines ) { + Lock l( mResourceLock ); + bool modified = false; + for ( auto& [dc, bp] : mBreakpoints ) { + if ( dc != doc ) + continue; + + if ( bp.line - 1 >= fromLine ) { + bp.line += numLines; + modified = true; + } + } + + if ( modified ) + invalidate( UpdateFlag::DontInvalidateIndexes ); +} + const std::pair& BreakpointsModel::get( ModelIndex index ) { static std::pair EMPTY = {}; if ( !index.isValid() || index.row() >= static_cast( mBreakpoints.size() ) ) diff --git a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp index 3d4cbbc07..514ed3875 100644 --- a/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp +++ b/src/tools/ecode/plugins/debugger/models/breakpointsmodel.hpp @@ -38,6 +38,8 @@ class BreakpointsModel : public Model { void enable( const std::string& filePath, const SourceBreakpointStateful& breakpoint, bool enable ); + void move( const std::string& doc, Int64 fromLine, Int64 toLine, Int64 numLines ); + const std::pair& get( ModelIndex index ); protected: std::vector> mBreakpoints; diff --git a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp index 11977ba37..9d8c346e6 100644 --- a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp +++ b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.hpp @@ -73,15 +73,15 @@ class XMLToolsPlugin : public PluginBase { mDoc( doc ), mParent( parent ) {} virtual void onDocumentTextChanged( const DocumentContentChange& ); - virtual void onDocumentUndoRedo( const TextDocument::UndoRedo& ) {}; - virtual void onDocumentCursorChange( const TextPosition& ) {}; - virtual void onDocumentInterestingCursorChange( const TextPosition& ) {}; + virtual void onDocumentUndoRedo( const TextDocument::UndoRedo& ) {} + virtual void onDocumentCursorChange( const TextPosition& ) {} + virtual void onDocumentInterestingCursorChange( const TextPosition& ) {} virtual void onDocumentSelectionChange( const TextRange& ); - virtual void onDocumentLineCountChange( const size_t&, const size_t& ) {}; - virtual void onDocumentLineChanged( const Int64& ) {}; - virtual void onDocumentSaved( TextDocument* ) {}; - virtual void onDocumentClosed( TextDocument* doc ) { onDocumentReset( doc ); }; - virtual void onDocumentDirtyOnFileSystem( TextDocument* ) {}; + virtual void onDocumentLineCountChange( const size_t&, const size_t& ) {} + virtual void onDocumentLineChanged( const Int64& ) {} + virtual void onDocumentSaved( TextDocument* ) {} + virtual void onDocumentClosed( TextDocument* doc ) { onDocumentReset( doc ); } + virtual void onDocumentDirtyOnFileSystem( TextDocument* ) {} virtual void onDocumentMoved( TextDocument* ) {}; virtual void onDocumentReset( TextDocument* ) { mSelections.clear(); }