diff --git a/.ecode/project_build.json b/.ecode/project_build.json index 5e8d73e8a..0d2c8d619 100644 --- a/.ecode/project_build.json +++ b/.ecode/project_build.json @@ -205,39 +205,39 @@ "run": [ { "args": "-v", - "command": "ecode-debug", + "command": "${project_root}/bin/ecode-debug", "name": "ecode-debug", "working_dir": "${project_root}/bin" }, { "args": "-x", - "command": "ecode", + "command": "${project_root}/bin/ecode", "name": "ecode-release", "working_dir": "${project_root}/bin" }, { "args": "", - "command": "eepp-unit_tests-debug", + "command": "${project_root}/bin/eepp-unit-tests-debug", "name": "eepp-unit_tests-debug", "run_in_terminal": true, - "working_dir": "${project_root}/bin/unit_tests" + "working_dir": "${project_root}/bin/unit_tests/" }, { "args": "", - "command": "eepp-unit_tests", + "command": "${project_root}/bin/eepp-unit_tests", "name": "eepp-unit_tests", "run_in_terminal": true, "working_dir": "${project_root}/bin/unit_tests" }, { "args": "", - "command": "eepp-empty-window-debug", + "command": "${project_root}/bin/eepp-empty-window-debug", "name": "eepp-empty_window-debug", "working_dir": "${project_root}/bin" }, { "args": "", - "command": "eepp-empty-window", + "command": "${project_root}/bin/eepp-empty-window", "name": "eepp-empty_window", "working_dir": "${project_root}/bin" } diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 4106fb44e..88da28298 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -1814,7 +1814,7 @@ std::map App::getLocalKeybindings() { { { KEY_5, KEYMOD_LALT }, "toggle-status-app-output" }, { { KEY_B, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "project-build-start" }, { { KEY_C, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "project-build-cancel" }, - { { KEY_F5, KEYMOD_NONE }, "project-build-and-run" }, + { { KEY_R, KeyMod::getDefaultModifier() }, "project-build-and-run" }, { { KEY_O, KEYMOD_LALT | KEYMOD_SHIFT }, "show-open-documents" }, { { KEY_K, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-workspace-symbol-search" }, { { KEY_P, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-document-symbol-search" }, @@ -1822,7 +1822,7 @@ std::map App::getLocalKeybindings() { }; } -// Old keybindings will be rebinded to the new keybindings of they are still set to the old +// Old keybindings will be rebinded to the new keybindings when they are still set to the old // keybindind std::map App::getMigrateKeybindings() { return { { "fullscreen-toggle", "alt+return" }, { "switch-to-tab-1", "alt+1" }, @@ -1834,7 +1834,8 @@ std::map App::getMigrateKeybindings() { #if EE_PLATFORM == EE_PLATFORM_MACOS { "menu-toggle", "mod+shift+m" }, #endif - { "lock-toggle", "mod+shift+l" }, { "debug-widget-tree-view", "f11" } }; + { "lock-toggle", "mod+shift+l" }, { "debug-widget-tree-view", "f11" }, + { "project-build-and-run", "f5" } }; } std::vector App::getUnlockedCommands() { @@ -1908,7 +1909,8 @@ void App::saveProject( bool onlyIfNeeded, bool sessionSnapshotEnabled ) { mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig, mProjectBuildManager ? mProjectBuildManager->getConfig() : ProjectBuildConfiguration(), - onlyIfNeeded, sessionSnapshotEnabled && mConfig.workspace.sessionSnapshot, mPluginManager.get() ); + onlyIfNeeded, sessionSnapshotEnabled && mConfig.workspace.sessionSnapshot, + mPluginManager.get() ); } } diff --git a/src/tools/ecode/featureshealth.cpp b/src/tools/ecode/featureshealth.cpp index 3a6980dca..4b3c70b7f 100644 --- a/src/tools/ecode/featureshealth.cpp +++ b/src/tools/ecode/featureshealth.cpp @@ -109,12 +109,13 @@ 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 ) ); + FeatureStatus fdbg; + fdbg.name = dbg.name; + fdbg.url = dbg.url; + auto debuggerBin = debugger->debuggerBinaryExists( dbg.name ); + fdbg.path = debuggerBin ? debuggerBin->command : ""; + fdbg.found = !fdbg.path.empty(); + lang.debugger.emplace_back( std::move( fdbg ) ); } } diff --git a/src/tools/ecode/plugins/debugger/dap/protocol.cpp b/src/tools/ecode/plugins/debugger/dap/protocol.cpp index b3dec45fc..d221dc66e 100644 --- a/src/tools/ecode/plugins/debugger/dap/protocol.cpp +++ b/src/tools/ecode/plugins/debugger/dap/protocol.cpp @@ -249,7 +249,7 @@ ThreadEvent::ThreadEvent( const json& body ) : StoppedEvent::StoppedEvent( const json& body ) : reason( body[DAP_REASON].get() ), description( parseOptionalString( body, "description" ) ), - threadId( body[DAP_THREAD_ID].get() ), + threadId( body.value( DAP_THREAD_ID, 1 ) ), preserveFocusHint( parseOptionalBool( body, "preserveFocusHint" ) ), text( parseOptionalString( body, "text" ) ), allThreadsStopped( parseOptionalBool( body, "allThreadsStopped" ) ), diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp index 3f80bb699..bb49ec12c 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.cpp @@ -5,6 +5,7 @@ #include "models/stackmodel.hpp" #include "models/threadsmodel.hpp" #include "models/variablesmodel.hpp" +#include #include #include @@ -101,17 +102,30 @@ void DebuggerClientListener::stateChanged( DebuggerClient::State state ) { } } -void DebuggerClientListener::initialized() { +void DebuggerClientListener::sendBreakpoints() { Lock l( mPlugin->mBreakpointsMutex ); - for ( const auto& fileBps : mPlugin->mBreakpoints ) - mClient->setBreakpoints( fileBps.first, fromSet( fileBps.second ) ); + for ( const auto& fileBps : mPlugin->mBreakpoints ) { + std::string path( fileBps.first ); + if ( isRemote() ) { + FileSystem::filePathRemoveBasePath( mPlugin->mProjectPath, path ); + path = "/" + path; + } + mClient->setBreakpoints( path, fromSet( fileBps.second ) ); + } +} + +void DebuggerClientListener::initialized() { + sendBreakpoints(); } void DebuggerClientListener::launched() {} void DebuggerClientListener::configured() {} -void DebuggerClientListener::failed() {} +void DebuggerClientListener::failed() { + mPlugin->exitDebugger(); + resetState(); +} void DebuggerClientListener::debuggeeRunning() {} @@ -184,6 +198,10 @@ void DebuggerClientListener::debuggingProcess( const ProcessInfo& ) {} void DebuggerClientListener::errorResponse( const std::string& command, const std::string& summary, const std::optional& /*message*/ ) { if ( command != "evaluate" ) { + if ( command == "launch" ) { + failed(); + } + mPlugin->getPluginContext()->getNotificationCenter()->addNotification( summary, Seconds( 5 ) ); } @@ -328,6 +346,10 @@ void DebuggerClientListener::expressionEvaluated( const std::string& /*expressio void DebuggerClientListener::gotoTargets( const Source& /*source*/, const int /*line*/, const std::vector& /*targets*/ ) {} +bool DebuggerClientListener::isRemote() const { + return mIsRemote; +} + bool DebuggerClientListener::isStopped() const { return mStoppedData ? true : false; } @@ -352,6 +374,10 @@ std::optional> DebuggerClientListener::getCurrentSco return mCurrentScopePos; } +void DebuggerClientListener::setIsRemote( bool isRemote ) { + mIsRemote = isRemote; +} + StatusDebuggerController* DebuggerClientListener::getStatusDebuggerController() const { return mPlugin->getStatusDebuggerController(); } diff --git a/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp b/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp index 82d35c773..c93348c9d 100644 --- a/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp @@ -53,6 +53,8 @@ class DebuggerClientListener : public DebuggerClient::Listener { void gotoTargets( const Source& source, const int line, const std::vector& targets ); + bool isRemote() const; + bool isStopped() const; std::optional getStoppedData() const; @@ -65,12 +67,17 @@ class DebuggerClientListener : public DebuggerClient::Listener { std::optional> getCurrentScopePos() const; + void setIsRemote( bool isRemote ); + + void sendBreakpoints(); + protected: DebuggerClient* mClient{ nullptr }; DebuggerPlugin* mPlugin{ nullptr }; std::optional mStoppedData; std::optional> mCurrentScopePos; bool mPausedToRefreshBreakpoints{ false }; + bool mIsRemote{ false }; int mCurrentThreadId{ 1 }; int mCurrentFrameId{ 0 }; std::shared_ptr mThreadsModel; diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index 1f8170c87..2e727d211 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -625,8 +625,11 @@ void DebuggerPlugin::buildSidePanelTab() { mTabContents->bind( "debugger_conf_list", mUIDebuggerConfList ); mUIDebuggerList->on( Event::OnValueChange, [this]( const Event* event ) { - mCurDebugger = event->getNode()->asType()->getText().toUtf8(); - mCurConfiguration = ""; + auto cur = event->getNode()->asType()->getText().toUtf8(); + if ( cur != mCurDebugger ) { + mCurDebugger = std::move( cur ); + mCurConfiguration = ""; + } } ); mUIDebuggerConfList->on( Event::OnValueChange, [this]( const Event* event ) { @@ -886,14 +889,13 @@ void DebuggerPlugin::sendFileBreakpoints( const std::string& filePath ) { return; } - Lock l( mBreakpointsMutex ); - auto fileBps = mBreakpoints.find( filePath ); - if ( fileBps == mBreakpoints.end() ) - return; - for ( const auto& fileBps : mBreakpoints ) { - mDebugger->setBreakpoints( fileBps.first, - DebuggerClientListener::fromSet( fileBps.second ) ); + { + Lock l( mBreakpointsMutex ); + auto fileBps = mBreakpoints.find( filePath ); + if ( fileBps == mBreakpoints.end() ) + return; } + mListener->sendBreakpoints(); } void DebuggerPlugin::updateDebuggerConfigurationList() { @@ -1360,19 +1362,10 @@ void DebuggerPlugin::runConfig( const std::string& debugger, const std::string& for ( const std::string& cmdArg : configIt->cmdArgs ) runConfig.args.emplace_back( cmdArg ); - std::string findBinary; - auto findBinaryIt = debuggerIt->findBinary.find( String::toLower( Sys::getPlatform() ) ); - if ( findBinaryIt != debuggerIt->findBinary.end() ) - findBinary = findBinaryIt->second; - - std::string fallbackCommand = debuggerIt->fallbackCommand; - mThreadPool->run( [this, protocolSettings = std::move( protocolSettings ), - runSettings = std::move( runConfig ), findBinary = std::move( findBinary ), - fallbackCommand = std::move( fallbackCommand ), randomPort]() mutable { - run( std::move( protocolSettings ), std::move( runSettings ), std::move( findBinary ), - std::move( fallbackCommand ), randomPort ); + runSettings = std::move( runConfig ), randomPort, debugger]() mutable { + run( debugger, std::move( protocolSettings ), std::move( runSettings ), randomPort ); }, [this]( const Uint64& ) { if ( !mDebugger || !mDebugger->started() ) { @@ -1384,13 +1377,28 @@ void DebuggerPlugin::runConfig( const std::string& debugger, const std::string& } ); } -void DebuggerPlugin::run( ProtocolSettings&& protocolSettings, DapRunConfig&& runConfig, - std::string&& findBinary, std::string&& fallbackCommand, - int /*randPort*/ ) { +std::optional +DebuggerPlugin::debuggerBinaryExists( const std::string& debugger, + std::optional optRunConfig ) { + auto debuggerIt = std::find_if( mDaps.begin(), mDaps.end(), [&debugger]( const DapTool& dap ) { + return dap.name == debugger; + } ); + + if ( debuggerIt == mDaps.end() ) + return {}; + + DapRunConfig runConfig = optRunConfig ? *optRunConfig : debuggerIt->run; Command cmd; cmd.command = std::move( runConfig.command ); cmd.arguments = std::move( runConfig.args ); + std::string findBinary; + auto findBinaryIt = debuggerIt->findBinary.find( String::toLower( Sys::getPlatform() ) ); + if ( findBinaryIt != debuggerIt->findBinary.end() ) + findBinary = findBinaryIt->second; + + std::string fallbackCommand = debuggerIt->fallbackCommand; + if ( !findBinary.empty() && Sys::which( cmd.command ).empty() ) { auto foundCmd = findCommand( findBinary, cmd.command ); if ( !foundCmd.empty() ) { @@ -1402,27 +1410,43 @@ void DebuggerPlugin::run( ProtocolSettings&& protocolSettings, DapRunConfig&& ru } } - if ( protocolSettings.launchCommand == REQUEST_TYPE_LAUNCH && !cmd.command.empty() && - !FileSystem::fileExists( cmd.command ) && Sys::which( cmd.command ).empty() ) { + if ( !cmd.command.empty() && !FileSystem::fileExists( cmd.command ) && + Sys::which( cmd.command ).empty() ) { auto args = Process::parseArgs( cmd.command ); - if ( args.size() <= 1 || + if ( args.empty() || ( !FileSystem::fileExists( args[0] ) && Sys::which( args[0] ).empty() ) ) { if ( fallbackCommand.empty() || ( !FileSystem::fileExists( fallbackCommand ) && Sys::which( fallbackCommand ).empty() ) ) { - auto msg = String::format( - i18n( "debugger_binary_not_found", - "Debugger binary not found. Binary \"%s\" must be installed." ) - .toUtf8(), - cmd.command ); - - mManager->getPluginContext()->getNotificationCenter()->addNotification( msg ); - return; + return {}; } else { cmd.command = std::move( fallbackCommand ); } } } + return cmd; +} + +void DebuggerPlugin::run( const std::string& debugger, ProtocolSettings&& protocolSettings, + DapRunConfig&& runConfig, int /*randPort*/ ) { + std::optional cmdOpt = debuggerBinaryExists( debugger, runConfig ); + + if ( !cmdOpt && ( protocolSettings.launchCommand == REQUEST_TYPE_LAUNCH || + ( protocolSettings.launchCommand == REQUEST_TYPE_ATTACH && + protocolSettings.launchRequest.value( "mode", "" ) == "local" ) ) ) { + auto msg = + String::format( i18n( "debugger_binary_not_found", + "Debugger binary not found. Binary \"%s\" must be installed." ) + .toUtf8(), + runConfig.command ); + + mManager->getPluginContext()->getNotificationCenter()->addNotification( msg ); + return; + } + + Command cmd = std::move( *cmdOpt ); + bool isRemote = false; + if ( protocolSettings.launchCommand == REQUEST_TYPE_LAUNCH ) { auto bus = std::make_unique( cmd ); mDebugger = std::make_unique( protocolSettings, std::move( bus ) ); @@ -1452,6 +1476,7 @@ void DebuggerPlugin::run( ProtocolSettings&& protocolSettings, DapRunConfig&& ru } else if ( mode == "remote" ) { auto bus = std::make_unique( con ); mDebugger = std::make_unique( protocolSettings, std::move( bus ) ); + isRemote = true; } } else { getManager()->getPluginContext()->getNotificationCenter()->addNotification( String::format( @@ -1461,12 +1486,14 @@ void DebuggerPlugin::run( ProtocolSettings&& protocolSettings, DapRunConfig&& ru } if ( !mDebugger ) { - getManager()->getPluginContext()->getNotificationCenter()->addNotification( i18n( - "debugger_configuration_not_supported", "Debugger configuration not supported." ) ); + getManager()->getPluginContext()->getNotificationCenter()->addNotification( + i18n( "debugger_configuration_not_supported", + "Debugger configuration currently not supported." ) ); return; } mListener = std::make_unique( mDebugger.get(), this ); + mListener->setIsRemote( isRemote ); mDebugger->addListener( mListener.get() ); DebuggerClientDap* dap = static_cast( mDebugger.get() ); diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp index 97f8ac332..b35fda66e 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp @@ -64,6 +64,9 @@ class DebuggerPlugin : public PluginBase { std::vector getDebuggersForLang( const std::string& lang ); + std::optional debuggerBinaryExists( const std::string& debugger, + std::optional runConfig = {} ); + protected: friend class DebuggerClientListener; @@ -142,8 +145,8 @@ class DebuggerPlugin : public PluginBase { void runConfig( const std::string& debugger, const std::string& configuration ); - void run( ProtocolSettings&& protocolSettings, DapRunConfig&& runConfig, - std::string&& findBinary, std::string&& fallbackCommand, int randPort ); + void run( const std::string& debugger, ProtocolSettings&& protocolSettings, + DapRunConfig&& runConfig, int randPort ); void exitDebugger(); diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index e5ea27919..87063a69c 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -572,7 +572,7 @@ void TerminalManager::setKeybindings( UITerminal* term ) { "debug-draw-boxes-toggle", "debug-draw-debug-data", "debug-widget-tree-view", "open-locatebar", "open-command-palette", "open-global-search", "menu-toggle", "console-toggle", "go-to-line", "editor-go-back", "editor-go-forward", - "project-run-executable", "project-build-and-run" } ); + "project-run-executable" } ); } } // namespace ecode