From fb3b866f29cdc1c53d8b3ffefac0e08dd8acad6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 13 Jan 2025 01:24:30 -0300 Subject: [PATCH] More fixes. Added debuggers to health tool. --- src/tools/ecode/featureshealth.cpp | 118 +++++++++++++++++- src/tools/ecode/featureshealth.hpp | 1 + .../autocomplete/autocompleteplugin.cpp | 4 + .../debugger/debuggerclientlistener.cpp | 24 ++-- .../ecode/plugins/debugger/debuggerplugin.cpp | 33 ++++- .../ecode/plugins/debugger/debuggerplugin.hpp | 3 + .../debugger/models/variablesmodel.cpp | 8 +- .../ecode/plugins/linter/linterplugin.cpp | 12 +- .../ecode/plugins/lsp/lspclientplugin.cpp | 5 +- 9 files changed, 179 insertions(+), 29 deletions(-) diff --git a/src/tools/ecode/featureshealth.cpp b/src/tools/ecode/featureshealth.cpp index ea81922e7..3a6980dca 100644 --- a/src/tools/ecode/featureshealth.cpp +++ b/src/tools/ecode/featureshealth.cpp @@ -1,4 +1,5 @@ #include "featureshealth.hpp" +#include "plugins/debugger/debuggerplugin.hpp" #include "plugins/formatter/formatterplugin.hpp" #include "plugins/linter/linterplugin.hpp" #include "plugins/lsp/lspclientplugin.hpp" @@ -28,6 +29,7 @@ std::vector FeaturesHealth::getHealth( PluginManager bool ownsLinter = false; bool ownsFormatter = false; bool ownsLSP = false; + bool ownsDebugger = false; const auto& definitions = SyntaxDefinitionManager::instance()->getDefinitions(); @@ -38,6 +40,8 @@ std::vector FeaturesHealth::getHealth( PluginManager LSPClientPlugin* lsp = static_cast( pluginManager->get( "lspclient" ) ); + DebuggerPlugin* debugger = static_cast( pluginManager->get( "debugger" ) ); + if ( !linter ) { ownsLinter = true; linter = static_cast( LinterPlugin::NewSync( pluginManager ) ); @@ -52,6 +56,11 @@ std::vector FeaturesHealth::getHealth( PluginManager lsp = static_cast( LSPClientPlugin::NewSync( pluginManager ) ); } + if ( !debugger ) { + ownsDebugger = true; + debugger = static_cast( DebuggerPlugin::NewSync( pluginManager ) ); + } + for ( const auto& def : definitions ) { if ( !def.isVisible() ) continue; @@ -97,6 +106,18 @@ std::vector FeaturesHealth::getHealth( PluginManager } } + if ( debugger ) { + std::vector found = debugger->getDebuggersForLang( def.getLSPName() ); + for ( const auto& dbg : found ) { + FeatureStatus debugger; + debugger.name = dbg.name; + debugger.url = dbg.url; + debugger.path = Sys::which( dbg.run.command ); + debugger.found = !debugger.path.empty(); + lang.debugger.emplace_back( std::move( debugger ) ); + } + } + langs.emplace_back( std::move( lang ) ); } @@ -109,6 +130,9 @@ std::vector FeaturesHealth::getHealth( PluginManager if ( ownsLSP ) eeSAFE_DELETE( lsp ); + if ( ownsDebugger ) + eeSAFE_DELETE( debugger ); + std::sort( langs.begin(), langs.end(), sortKey ); return langs; @@ -121,9 +145,9 @@ std::string FeaturesHealth::generateHealthStatus( PluginManager* pluginManager, table.format().border_top( "" ).border_bottom( "" ).border_left( "" ).border_right( "" ).corner( "" ); - size_t numRows = 5; + size_t numRows = 6; - table.add_row( { "Language", "Highlight", "LSP", "Linter", "Formatter" } ); + table.add_row( { "Language", "Highlight", "LSP", "Linter", "Formatter", "Debugger" } ); for ( size_t i = 0; i < numRows; ++i ) { table[0][i] @@ -155,7 +179,23 @@ std::string FeaturesHealth::generateHealthStatus( PluginManager* pluginManager, formatterName = "[" + ht.formatter.name + "](" + ht.formatter.url + ")"; } - table.add_row( { ht.lang, check, lspName, linterName, formatterName } ); + std::string debuggerName = + ht.debugger.empty() + ? "None" + : std::accumulate( ht.debugger.begin(), ht.debugger.end(), std::string{}, + []( const std::string& acc, const FeatureStatus& item ) { + return acc.empty() ? item.name : acc + " / " + item.name; + } ); + if ( OutputFormat::Markdown == format && !ht.debugger.empty() ) { + debuggerName = std::accumulate( + ht.debugger.begin(), ht.debugger.end(), std::string{}, + []( const std::string& acc, const FeatureStatus& item ) { + return acc.empty() ? "[" + item.name + "](" + item.url + ")" + : acc + " / " + "[" + item.name + "](" + item.url + ")"; + } ); + } + + table.add_row( { ht.lang, check, lspName, linterName, formatterName, debuggerName } ); auto& row = table[table.size() - 1]; @@ -181,6 +221,16 @@ std::string FeaturesHealth::generateHealthStatus( PluginManager* pluginManager, } else { row[4].format().font_color( tabulate::Color::yellow ); } + + if ( !ht.debugger.empty() ) { + row[5].format().font_color( + std::any_of( ht.debugger.begin(), ht.debugger.end(), + []( const FeatureStatus& item ) { return item.found; } ) + ? tabulate::Color::green + : tabulate::Color::red ); + } else { + row[5].format().font_color( tabulate::Color::yellow ); + } } if ( OutputFormat::Markdown == format ) { @@ -239,6 +289,21 @@ void FeaturesHealth::doHealth( PluginManager* pluginManager, const std::string& std::cout << "Configured formatter: " << formatterName << "\n\033[00m"; if ( !hr.formatter.name.empty() ) std::cout << "Binary for formatter: " << formatterBinary << "\n\033[00m"; + + if ( !hr.debugger.empty() ) { + for ( const auto& dbg : hr.debugger ) { + std::string debuggerName = + hr.debugger.empty() ? "\033[33mNone" : "\033[32m" + dbg.name; + std::string debuggerBinary = + dbg.found ? "\033[32m" + dbg.path : "\033[31m" + notFound; + + std::cout << "Configured debugger: " << debuggerName << "\n\033[00m"; + if ( !dbg.name.empty() ) + std::cout << "Binary for debugger: " << debuggerBinary << "\n\033[00m"; + } + } else { + std::cout << "Configured debugger: " << "\033[31m" + notFound << "\n\033[00m"; + } } } @@ -254,11 +319,11 @@ class HealthModel : public Model { virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } - virtual size_t columnCount( const ModelIndex& ) const { return 5; } + virtual size_t columnCount( const ModelIndex& ) const { return 6; } virtual std::string columnName( const size_t& idx ) const { - static const std::vector columns = { "language", "highlight", "LSP", "linter", - "formatter" }; + static const std::vector columns = { "language", "highlight", "LSP", + "linter", "formatter", "debugger" }; if ( idx < columns.size() ) return mSceneNode->i18n( columns[idx], String::capitalize( columns[idx] ) ); return ""; @@ -297,6 +362,16 @@ class HealthModel : public Model { return Variant( lang.linter.name.empty() ? none : lang.linter.name ); case 4: return Variant( lang.formatter.name.empty() ? none : lang.formatter.name ); + case 5: + return Variant( + lang.debugger.empty() + ? none + : std::accumulate( + lang.debugger.begin(), lang.debugger.end(), std::string{}, + []( const std::string& acc, + const FeaturesHealth::FeatureStatus& item ) { + return acc.empty() ? item.name : acc + " / " + item.name; + } ) ); default: { } } @@ -324,6 +399,18 @@ class HealthModel : public Model { else return Variant( HEALTH_NONE ); break; + case 5: + if ( !lang.debugger.empty() ) + return Variant( + std::any_of( lang.debugger.begin(), lang.debugger.end(), + []( const FeaturesHealth::FeatureStatus& item ) { + return item.found; + } ) + ? HEALTH_SUCCESS + : HEALTH_ERROR ); + else + return Variant( HEALTH_NONE ); + break; default: { } } @@ -463,6 +550,25 @@ void FeaturesHealth::displayHealth( PluginManager* pluginManager, UISceneNode* s lang.formatter.path.empty() ? patherr : "" ); } + for ( const auto& debugger : lang.debugger ) { + type = debugger.url.empty() ? "TextView" + : String::format( "Anchor href='%s'", debugger.url ); + l += String::format( "<%s text='%s' class='%s' />", + I18N( "configured_debugger", "Configured debugger" ), type, + debugger.name.empty() ? none : debugger.name, + debugger.found ? "success" + : ( debugger.name.empty() ? "none" : "error" ) ); + + if ( !debugger.name.empty() ) { + l += String::format( "", + I18N( "binary_for_debugger", "Binary for debugger" ), + debugger.path.empty() ? notFound : debugger.path, + !debugger.path.empty() ? "success" : "error", + debugger.path.empty() ? patherr : "" ); + } + } + sceneNode->loadLayoutFromString( l, healthLangInfo ); healthLangInfo->setVisible( true ); } ); diff --git a/src/tools/ecode/featureshealth.hpp b/src/tools/ecode/featureshealth.hpp index 6fff5db25..0994e2e22 100644 --- a/src/tools/ecode/featureshealth.hpp +++ b/src/tools/ecode/featureshealth.hpp @@ -38,6 +38,7 @@ class FeaturesHealth { FeatureStatus linter; FeatureStatus formatter; FeatureStatus lsp; + std::vector debugger; }; static std::vector getHealth( PluginManager* pluginManager, diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 92e8e4b8c..142530825 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -1226,6 +1226,10 @@ bool AutoCompletePlugin::onMouseMove( UICodeEditor* editor, const Vector2i& posi return false; Vector2f localPos( editor->convertToNodeSpace( position.asFloat() ) ); + + if ( localPos.x <= editor->getGutterWidth() ) + return false; + if ( mBoxRect.contains( localPos ) ) { editor->getUISceneNode()->setCursor( Cursor::Hand ); return true; diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp index 2993b884a..35ed706df 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp @@ -156,9 +156,8 @@ void DebuggerClientListener::debuggeeStopped( const StoppedEvent& event ) { mPlugin->setUIDebuggingState( StatusDebuggerController::State::Paused ); auto sdc = getStatusDebuggerController(); - if ( sdc ) { + if ( sdc ) sdc->getWidget()->runOnMainThread( [sdc] { sdc->show(); } ); - } } void DebuggerClientListener::debuggeeContinued( const ContinuedEvent& ) { @@ -216,18 +215,19 @@ void DebuggerClientListener::changeScope( const StackFrame& f ) { mCurrentScopePos = { f.source->path, f.line }; - if ( getStatusDebuggerController() && getStatusDebuggerController()->getUIStack() ) - getStatusDebuggerController()->getUIStack()->setSelection( mStackModel->index( f.id ) ); + auto sdc = getStatusDebuggerController(); + if ( sdc && sdc->getUIStack() ) + sdc->getUIStack()->setSelection( mStackModel->index( f.id ) ); } void DebuggerClientListener::changeThread( int id ) { mCurrentThreadId = id; if ( mThreadsModel ) mThreadsModel->setCurrentThreadId( id ); - if ( getStatusDebuggerController() && getStatusDebuggerController()->getUIThreads() ) { - getStatusDebuggerController()->getUIThreads()->setSelection( - mThreadsModel->fromThreadId( id ) ); - } + + auto sdc = getStatusDebuggerController(); + if ( sdc && sdc->getUIThreads() ) + sdc->getUIThreads()->setSelection( mThreadsModel->fromThreadId( id ) ); } void DebuggerClientListener::stackTrace( const int threadId, StackTraceInfo&& stack ) { @@ -270,14 +270,17 @@ void DebuggerClientListener::scopes( const int /*frameId*/, std::vector&& mVariablesHolder->clear(); for ( const auto& scope : scopes ) { + if ( !mPlugin->mDisplayRegisters && scope.name == "Registers" ) + continue; auto child = std::make_shared( scope.name, scope.variablesReference ); mVariablesHolder->addChild( child ); mClient->variables( scope.variablesReference ); } - if ( !getStatusDebuggerController() ) + auto sdc = getStatusDebuggerController(); + if ( nullptr == sdc ) return; - auto uiVars = getStatusDebuggerController()->getUIVariables(); + auto uiVars = sdc->getUIVariables(); if ( uiVars ) { uiVars->runOnMainThread( [uiVars] { auto model = uiVars->getModel(); @@ -307,6 +310,7 @@ void DebuggerClientListener::breakpointChanged( const BreakpointEvent& ) {} void DebuggerClientListener::expressionEvaluated( const std::string& /*expression*/, const std::optional& ) {} + void DebuggerClientListener::gotoTargets( const Source& /*source*/, const int /*line*/, const std::vector& /*targets*/ ) {} diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index d38f666e2..85df33714 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -205,6 +205,17 @@ void DebuggerPlugin::onLoadProject( const std::string& projectFolder, } } +std::vector DebuggerPlugin::getDebuggersForLang( const std::string& language ) { + std::vector tools; + for ( const auto& dap : mDaps ) { + auto found = std::find_if( dap.languagesSupported.begin(), dap.languagesSupported.end(), + [&language]( const auto& l ) { return l == language; } ); + if ( found != dap.languagesSupported.end() ) + tools.push_back( dap ); + } + return tools; +} + void DebuggerPlugin::resetExpressions() { if ( !mExpressionsHolder ) return; @@ -306,6 +317,14 @@ void DebuggerPlugin::loadDAPConfig( const std::string& path, bool updateConfigFi true, true ); } + if ( j.contains( "config" ) ) { + auto& config = j["config"]; + if ( config.contains( "display_registers" ) ) + mDisplayRegisters = config.value( "display_registers", false ); + else if ( updateConfigFile ) + config["display_registers"] = mDisplayRegisters; + } + if ( j.contains( "dap" ) ) { auto& dapArr = j["dap"]; mDaps.reserve( dapArr.size() ); @@ -577,7 +596,7 @@ void DebuggerPlugin::buildSidePanelTab() { - + @@ -1337,8 +1356,6 @@ void DebuggerPlugin::runConfig( const std::string& debugger, const std::string& std::string fallbackCommand = debuggerIt->fallbackCommand; - mRunButton->setEnabled( false ); - mThreadPool->run( [this, protocolSettings = std::move( protocolSettings ), runSettings = std::move( runConfig ), findBinary = std::move( findBinary ), @@ -1517,7 +1534,7 @@ void DebuggerPlugin::updatePanelUIState( StatusDebuggerController::State state ) mPanelBoxButtons.stepOut->setVisible( isDebugging ) ->setEnabled( state == StatusDebuggerController::State::Paused ); - mRunButton->setText( isDebugging ? i18n( "Stop Debugging", "Stop Debugging" ) + mRunButton->setText( isDebugging ? i18n( "Stop Debugger", "Stop Debugger" ) : i18n( "debug", "Debug" ) ); } @@ -1629,6 +1646,10 @@ bool DebuggerPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position return false; } + auto localPos( editor->convertToNodeSpace( position.asFloat() ) ); + if ( localPos.x <= editor->getGutterWidth() ) + return false; + editor->debounce( [this, editor, position]() { if ( !mManager->getSplitter()->editorExists( editor ) ) @@ -1637,7 +1658,8 @@ bool DebuggerPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position auto range = editor->getDocument().getWordRangeInPosition( docPos, true ); auto expression = editor->getDocument().getWordInPosition( docPos, true ).toUtf8(); - if ( !range.isValid() || expression.empty() ) + if ( !range.isValid() || expression.empty() || + LuaPattern::hasMatches( expression, "^[%p%s]+$" ) ) return; mCurrentHover = range; @@ -1667,6 +1689,7 @@ bool DebuggerPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position }, mHoverDelay, getMouseMoveHash( editor ) ); tryHideTooltip( editor, position ); + editor->updateMouseCursor( position.asFloat() ); return true; } diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp index 6aaf8a9f4..97f8ac332 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp @@ -62,10 +62,13 @@ class DebuggerPlugin : public PluginBase { void onLoadProject( const std::string& projectFolder, const std::string& projectStatePath ) override; + std::vector getDebuggersForLang( const std::string& lang ); + protected: friend class DebuggerClientListener; bool mInitialized{ false }; + bool mDisplayRegisters{ false }; std::string mProjectPath; std::vector mDaps; diff --git a/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp b/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp index fe9cb14b5..09933ee42 100644 --- a/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp +++ b/src/tools/ecode/plugins/debugger/models/variablesmodel.cpp @@ -182,10 +182,12 @@ void VariablesHolder::addVariables( const int variablesReference, std::vectorgetChild( var.name ); if ( found ) { - ( *found )->var = std::move( var ); + ModelVariableNode::NodePtr child = *found; + child->var = std::move( var ); + + if ( child->var.variablesReference != 0 ) + nodeMap[child->var.variablesReference] = *found; - if ( ( *found )->var.variablesReference != 0 ) - nodeMap[( *found )->var.variablesReference] = *found; continue; } diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 00bc13e77..c834b0958 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -1,5 +1,5 @@ -#include "../../stringhelper.hpp" -#include "linterplugin.hpp" +#include "linterplugin.hpp" +#include "../../stringhelper.hpp" #include #include #include @@ -1295,11 +1295,15 @@ bool LinterPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& pos, const tryHideHoveringMatch( editor ); return false; } + + Vector2f localPos( editor->convertToNodeSpace( pos.asFloat() ) ); + TextPosition cursorPosition = editor->resolveScreenPosition( pos.asFloat() ); + if ( localPos.x <= editor->getGutterWidth() ) + return false; + Lock l( mMatchesMutex ); auto it = mMatches.find( editor->getDocumentRef().get() ); if ( it != mMatches.end() ) { - Vector2f localPos( editor->convertToNodeSpace( pos.asFloat() ) ); - TextPosition cursorPosition = editor->resolveScreenPosition( pos.asFloat() ); auto matchIt = it->second.find( cursorPosition.line() ); if ( matchIt != it->second.end() ) { auto& matches = matchIt->second; diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index 31738d88c..2e54a3f92 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -1830,8 +1830,11 @@ void LSPClientPlugin::tryDisplayTooltip( UICodeEditor* editor, const LSPHover& r bool LSPClientPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position, const Uint32& flags ) { + auto localPos( editor->convertToNodeSpace( position.asFloat() ) ); + if ( localPos.x <= editor->getGutterWidth() ) + return false; + if ( mBreadcrumb ) { - auto localPos( editor->convertToNodeSpace( position.asFloat() ) ); if ( localPos.y < mPluginTopSpace && localPos.x < editor->getTopAreaWidth() && localPos.x >= 0 ) { if ( !mHoveringBreadcrumb ) {