From 4913443d73c05555c1470e5474c0e9c179a9a737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Tue, 14 Jan 2025 01:00:14 -0300 Subject: [PATCH] WIP expanded scope childs persistency (not working). Fix enable/disable vertical scrollbar in editor not updating line-wrap. --- src/eepp/ui/uicodeeditor.cpp | 1 + .../debugger/debuggerclientlistener.cpp | 11 +++ .../debugger/debuggerclientlistener.hpp | 1 + .../debugger/models/variablesmodel.cpp | 85 +++++++++++++++++++ .../debugger/models/variablesmodel.hpp | 68 +++++++++++++++ 5 files changed, 166 insertions(+) diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 5f7e74774..2f74870e4 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -3407,6 +3407,7 @@ bool UICodeEditor::getVerticalScrollBarEnabled() const { void UICodeEditor::setVerticalScrollBarEnabled( const bool& verticalScrollBarEnabled ) { if ( verticalScrollBarEnabled != mVerticalScrollBarEnabled ) { mVerticalScrollBarEnabled = verticalScrollBarEnabled; + invalidateLongestLineWidth(); updateScrollBar(); } } diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp index 35ed706df..528609971 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp @@ -88,6 +88,7 @@ void DebuggerClientListener::initUI() { ModelVariableNode* node = static_cast( modelEvent->getModelIndex().internalData() ); mClient->variables( node->var.variablesReference ); + mVariablesHolder->saveExpandedState( modelEvent->getModelIndex() ); } } ); @@ -277,6 +278,9 @@ void DebuggerClientListener::scopes( const int /*frameId*/, std::vector&& mClient->variables( scope.variablesReference ); } + for ( auto& scope : scopes ) + mScopeRef[scope.variablesReference] = std::move( scope ); + auto sdc = getStatusDebuggerController(); if ( nullptr == sdc ) return; @@ -293,6 +297,13 @@ void DebuggerClientListener::scopes( const int /*frameId*/, std::vector&& void DebuggerClientListener::variables( const int variablesReference, std::vector&& vars ) { mVariablesHolder->addVariables( variablesReference, std::move( vars ) ); + + auto scopeIt = mScopeRef.find( variablesReference ); + if ( mCurrentScopePos && scopeIt != mScopeRef.end() ) { + ExpandedState::Location location{ mCurrentScopePos->first, mCurrentScopePos->second, + mCurrentFrameId }; + mVariablesHolder->restoreExpandedState( location, mClient ); + } } void DebuggerClientListener::modules( ModulesInfo&& ) {} diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp index a186ad3f2..b98e48a8d 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp @@ -76,6 +76,7 @@ class DebuggerClientListener : public DebuggerClient::Listener { std::shared_ptr mThreadsModel; std::shared_ptr mStackModel; std::shared_ptr mVariablesHolder; + std::unordered_map mScopeRef; StatusDebuggerController* getStatusDebuggerController() const; diff --git a/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp b/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp index 09933ee42..c9360c85b 100644 --- a/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp +++ b/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp @@ -1,4 +1,5 @@ #include "variablesmodel.hpp" +#include "../debuggerclient.hpp" #include namespace ecode { @@ -240,4 +241,88 @@ ModelVariableNode::NodePtr VariablesHolder::getNodeByReference( int variablesRef return ( it != nodeMap.end() ) ? it->second : nullptr; } +VariablePath VariablesHolder::buildVariablePath( ModelVariableNode* node ) const { + VariablePath path; + std::vector reversePath; + + // Build the path from node to root + while ( node && node != rootNode.get() ) { + reversePath.push_back( node->getName() ); + node = node->parent ? node->parent.get() : nullptr; + } + + if ( reversePath.size() >= 2 ) { + path.scopeName = reversePath.back(); // The scope name is at the root + path.variableName = reversePath[reversePath.size() - 2]; // The variable name is next + + // Add any remaining path components as child path + path.childPath.assign( reversePath.begin(), reversePath.end() - 2 ); + } + + return path; +} + +void VariablesHolder::saveExpandedState( const ModelIndex& index ) { + if ( !currentLocation ) + return; + + ModelVariableNode* node = static_cast( index.internalData() ); + if ( !node ) + return; + + auto nodePath = buildVariablePath( node ); + expandedStates[*currentLocation].insert( std::move( nodePath ) ); +} + +void VariablesHolder::restoreExpandedState( const ExpandedState::Location& location, + DebuggerClient* client ) { + currentLocation = location; + + auto it = expandedStates.find( location ); + if ( it == expandedStates.end() ) + return; + + const auto& paths = it->second; + + for ( const auto& path : paths ) { + // Find the scope node + auto scopeNode = [this, &path]() -> ModelVariableNode::NodePtr { + for ( const auto& child : rootNode->children ) { + if ( child->getName() == path.scopeName ) { + return child; + } + } + return nullptr; + }(); + + if ( !scopeNode ) + continue; + + // Find the variable node + auto currentNode = [&path, scopeNode]() -> ModelVariableNode::NodePtr { + for ( const auto& child : scopeNode->children ) { + if ( child->getName() == path.variableName ) { + return child; + } + } + return nullptr; + }(); + + if ( !currentNode ) + continue; + + if ( currentNode->getVariablesReference() > 0 ) + client->variables( currentNode->getVariablesReference() ); + + for ( const auto& childName : path.childPath ) { + auto childOpt = currentNode->getChild( childName ); + if ( !childOpt ) + break; + + currentNode = *childOpt; + if ( currentNode->getVariablesReference() > 0 ) + client->variables( currentNode->getVariablesReference() ); + } + } +} } // namespace ecode diff --git a/src/tools/ecode/plugins/debugger/models/variablesmodel.hpp b/src/tools/ecode/plugins/debugger/models/variablesmodel.hpp index d10d24248..74bf72b73 100644 --- a/src/tools/ecode/plugins/debugger/models/variablesmodel.hpp +++ b/src/tools/ecode/plugins/debugger/models/variablesmodel.hpp @@ -15,6 +15,67 @@ namespace ecode { using namespace dap; +class DebuggerClient; + +struct VariablePath { + std::string scopeName; + std::string variableName; + std::vector childPath; + + bool operator==( const VariablePath& other ) const { + return scopeName == other.scopeName && variableName == other.variableName && + childPath == other.childPath; + } +}; + +} // namespace ecode + +namespace std { +template <> struct hash { + size_t operator()( const ecode::VariablePath& path ) const { + size_t h = std::hash{}( path.scopeName ); + h ^= std::hash{}( path.variableName ) + 0x9e3779b9 + ( h << 6 ) + ( h >> 2 ); + for ( const auto& child : path.childPath ) { + h ^= std::hash{}( child ) + 0x9e3779b9 + ( h << 6 ) + ( h >> 2 ); + } + return h; + } +}; + +} // namespace std + +namespace ecode { + +struct ExpandedState { + struct Location { + std::string filePath; + int lineNumber{}; + int frameIndex{}; + + bool operator==( const Location& other ) const { + return filePath == other.filePath && lineNumber == other.lineNumber && + frameIndex == other.frameIndex; + } + }; + + Location location; + std::unordered_set expandedPaths; +}; + +} // namespace ecode + +namespace std { +template <> struct hash { + size_t operator()( const ecode::ExpandedState::Location& loc ) const { + return hashCombine( std::hash{}( loc.filePath ), + std::hash{}( loc.lineNumber ), + std::hash{}( loc.frameIndex ) ); + } +}; +} // namespace std + +namespace ecode { + struct ModelVariableNode : public std::enable_shared_from_this { using NodePtr = std::shared_ptr; @@ -89,6 +150,13 @@ struct VariablesHolder { std::shared_ptr rootNode; std::shared_ptr model; std::unordered_map nodeMap; + + std::unordered_map> expandedStates; + std::optional currentLocation; + + VariablePath buildVariablePath( ModelVariableNode* node ) const; + void saveExpandedState( const ModelIndex& index ); + void restoreExpandedState( const ExpandedState::Location& location, DebuggerClient* client ); }; } // namespace ecode