mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
More WIP.
This commit is contained in:
@@ -1588,6 +1588,8 @@
|
||||
../../src/tools/ecode/plugins/debugger/debuggerclientlistener.hpp
|
||||
../../src/tools/ecode/plugins/debugger/debuggerplugin.cpp
|
||||
../../src/tools/ecode/plugins/debugger/debuggerplugin.hpp
|
||||
../../src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp
|
||||
../../src/tools/ecode/plugins/debugger/statusdebuggercontroller.hpp
|
||||
../../src/tools/ecode/plugins/formatter/formatterplugin.cpp
|
||||
../../src/tools/ecode/plugins/formatter/formatterplugin.hpp
|
||||
../../src/tools/ecode/notificationcenter.cpp
|
||||
|
||||
@@ -577,7 +577,10 @@ void App::initPluginManager() {
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef EE_DEBUG
|
||||
mPluginManager->registerPlugin( DebuggerPlugin::Definition() );
|
||||
#endif
|
||||
mPluginManager->registerPlugin( LinterPlugin::Definition() );
|
||||
mPluginManager->registerPlugin( FormatterPlugin::Definition() );
|
||||
mPluginManager->registerPlugin( AutoCompletePlugin::Definition() );
|
||||
|
||||
@@ -611,13 +611,13 @@ bool DebuggerClientDap::evaluate( const std::string& expression, const std::stri
|
||||
}
|
||||
|
||||
bool DebuggerClientDap::setBreakpoints( const std::string& path,
|
||||
const std::vector<dap::SourceBreakpoint> breakpoints,
|
||||
const std::vector<dap::SourceBreakpoint>& breakpoints,
|
||||
bool sourceModified ) {
|
||||
return setBreakpoints( Source( path ), breakpoints, sourceModified );
|
||||
}
|
||||
|
||||
bool DebuggerClientDap::setBreakpoints( const dap::Source& source,
|
||||
const std::vector<dap::SourceBreakpoint> breakpoints,
|
||||
const std::vector<dap::SourceBreakpoint>& breakpoints,
|
||||
bool sourceModified ) {
|
||||
nlohmann::json bpoints = nlohmann::json::array();
|
||||
for ( const auto& item : breakpoints )
|
||||
|
||||
@@ -57,11 +57,11 @@ class DebuggerClientDap : public DebuggerClient {
|
||||
bool supportsTerminate() const override;
|
||||
|
||||
bool setBreakpoints( const std::string& path,
|
||||
const std::vector<dap::SourceBreakpoint> breakpoints,
|
||||
const std::vector<dap::SourceBreakpoint>& breakpoints,
|
||||
bool sourceModified = false ) override;
|
||||
|
||||
bool setBreakpoints( const dap::Source& source,
|
||||
const std::vector<dap::SourceBreakpoint> breakpoints,
|
||||
const std::vector<dap::SourceBreakpoint>& breakpoints,
|
||||
bool sourceModified = false ) override;
|
||||
|
||||
bool gotoTargets( const std::string& path, const int line,
|
||||
|
||||
@@ -173,6 +173,16 @@ struct SourceBreakpoint {
|
||||
bool operator==( const SourceBreakpoint& other ) const { return line == other.line; }
|
||||
};
|
||||
|
||||
struct SourceBreakpointStateful : public SourceBreakpoint {
|
||||
bool enabled{ true };
|
||||
|
||||
SourceBreakpointStateful() = default;
|
||||
SourceBreakpointStateful( const json& body ) : SourceBreakpoint( body ) {}
|
||||
SourceBreakpointStateful( const int line ) : SourceBreakpoint( line ) {}
|
||||
|
||||
bool operator==( const SourceBreakpointStateful& other ) const { return line == other.line; }
|
||||
};
|
||||
|
||||
struct Breakpoint {
|
||||
/**
|
||||
* An optional identifier for the breakpoint. It is needed if breakpoint
|
||||
@@ -489,3 +499,16 @@ template <> struct std::hash<ecode::dap::SourceBreakpoint> {
|
||||
return hashCombine( h1, h2, h3, h4, h5 );
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct std::hash<ecode::dap::SourceBreakpointStateful> {
|
||||
std::size_t operator()( ecode::dap::SourceBreakpointStateful const& breakpoint ) const noexcept {
|
||||
size_t h1 = std::hash<int>()( breakpoint.line );
|
||||
size_t h2 = breakpoint.column ? std::hash<int>()( *breakpoint.column ) : 0;
|
||||
size_t h3 = breakpoint.condition ? std::hash<std::string>()( *breakpoint.condition ) : 0;
|
||||
size_t h4 =
|
||||
breakpoint.hitCondition ? std::hash<std::string>()( *breakpoint.hitCondition ) : 0;
|
||||
size_t h5 = breakpoint.logMessage ? std::hash<std::string>()( *breakpoint.logMessage ) : 0;
|
||||
size_t h6 = std::hash<bool>()( breakpoint.enabled );
|
||||
return hashCombine( h1, h2, h3, h4, h5, h6 );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -89,11 +89,11 @@ class DebuggerClient {
|
||||
virtual bool supportsTerminate() const = 0;
|
||||
|
||||
virtual bool setBreakpoints( const std::string& path,
|
||||
const std::vector<dap::SourceBreakpoint> breakpoints,
|
||||
const std::vector<dap::SourceBreakpoint>& breakpoints,
|
||||
bool sourceModified = false ) = 0;
|
||||
|
||||
virtual bool setBreakpoints( const dap::Source& source,
|
||||
const std::vector<dap::SourceBreakpoint> breakpoints,
|
||||
const std::vector<dap::SourceBreakpoint>& breakpoints,
|
||||
bool sourceModified = false ) = 0;
|
||||
|
||||
virtual bool gotoTargets( const std::string& path, const int line,
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
|
||||
namespace ecode {
|
||||
|
||||
static std::vector<SourceBreakpoint> fromSet( const UnorderedSet<SourceBreakpointStateful>& set ) {
|
||||
std::vector<SourceBreakpoint> bps;
|
||||
bps.reserve( set.size() );
|
||||
for ( const auto& bp : set )
|
||||
if ( bp.enabled )
|
||||
bps.emplace_back( bp );
|
||||
return bps;
|
||||
}
|
||||
|
||||
DebuggerClientListener::DebuggerClientListener( DebuggerClient* client, DebuggerPlugin* plugin ) :
|
||||
mClient( client ), mPlugin( plugin ) {
|
||||
eeASSERT( mClient && mPlugin );
|
||||
@@ -12,6 +21,8 @@ DebuggerClientListener::DebuggerClientListener( DebuggerClient* client, Debugger
|
||||
void DebuggerClientListener::stateChanged( DebuggerClient::State state ) {
|
||||
if ( state == DebuggerClient::State::Initializing ) {
|
||||
mPlugin->getManager()->getUISceneNode()->runOnMainThread( [this] {
|
||||
getStatusDebuggerController()->createWidget();
|
||||
|
||||
mPlugin->getManager()
|
||||
->getPluginContext()
|
||||
->getStatusAppOutputController()
|
||||
@@ -21,8 +32,9 @@ void DebuggerClientListener::stateChanged( DebuggerClient::State state ) {
|
||||
}
|
||||
|
||||
void DebuggerClientListener::initialized() {
|
||||
// mClient->setBreakpoints( "/home/programming/eepp/src/tools/ecode/ecode.cpp",
|
||||
// { SourceBreakpoint( 4116 ) } );
|
||||
Lock l( mPlugin->mBreakpointsMutex );
|
||||
for ( const auto& fileBps : mPlugin->mBreakpoints )
|
||||
mClient->setBreakpoints( fileBps.first, fromSet( fileBps.second ) );
|
||||
}
|
||||
|
||||
void DebuggerClientListener::launched() {}
|
||||
@@ -42,10 +54,10 @@ void DebuggerClientListener::debuggeeExited( int /*exitCode*/ ) {
|
||||
}
|
||||
|
||||
void DebuggerClientListener::debuggeeStopped( const StoppedEvent& event ) {
|
||||
Log::warning( "DebuggerClientListener::debuggeeStopped: reason %s", event.reason );
|
||||
// if ( event.threadId ) {
|
||||
// mClient->stackTrace( *event.threadId );
|
||||
// }
|
||||
Log::debug( "DebuggerClientListener::debuggeeStopped: reason %s", event.reason );
|
||||
mClient->threads();
|
||||
if ( event.threadId )
|
||||
mClient->stackTrace( *event.threadId );
|
||||
}
|
||||
|
||||
void DebuggerClientListener::debuggeeContinued( const ContinuedEvent& ) {}
|
||||
@@ -67,12 +79,93 @@ void DebuggerClientListener::threadChanged( const ThreadEvent& ) {}
|
||||
|
||||
void DebuggerClientListener::moduleChanged( const ModuleEvent& ) {}
|
||||
|
||||
void DebuggerClientListener::threads( const std::vector<Thread>& /*threads*/ ) {}
|
||||
class ThreadsModel : public Model {
|
||||
public:
|
||||
ThreadsModel( const std::vector<Thread>& threads ) : mThreads( threads ) {}
|
||||
virtual size_t rowCount( const ModelIndex& ) const { return mThreads.size(); }
|
||||
virtual size_t columnCount( const ModelIndex& ) const { return 2; }
|
||||
|
||||
virtual std::string columnName( const size_t& colIdx ) const {
|
||||
return colIdx == 0 ? "ID" : "Name";
|
||||
}
|
||||
|
||||
virtual Variant data( const ModelIndex& modelIndex, ModelRole role ) const {
|
||||
if ( role == ModelRole::Display ) {
|
||||
return modelIndex.column() == 0
|
||||
? Variant( String::toString( mThreads[modelIndex.row()].id ) )
|
||||
: Variant( mThreads[modelIndex.row()].name.c_str() );
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<Thread> mThreads;
|
||||
};
|
||||
|
||||
void DebuggerClientListener::threads( const std::vector<Thread>& threads ) {
|
||||
getStatusDebuggerController()->getUIThreads()->setModel(
|
||||
std::make_shared<ThreadsModel>( threads ) );
|
||||
}
|
||||
|
||||
class StackModel : public Model {
|
||||
public:
|
||||
StackModel( const StackTraceInfo& stack ) : mStack( stack ) {}
|
||||
virtual size_t rowCount( const ModelIndex& ) const { return mStack.stackFrames.size(); }
|
||||
virtual size_t columnCount( const ModelIndex& ) const { return 5; }
|
||||
|
||||
virtual std::string columnName( const size_t& colIdx ) const {
|
||||
switch ( colIdx ) {
|
||||
case 0:
|
||||
return "ID";
|
||||
case 1:
|
||||
return "Name";
|
||||
case 2:
|
||||
return "Source Name";
|
||||
case 3:
|
||||
return "Source Path";
|
||||
case 4:
|
||||
return "Line";
|
||||
case 5:
|
||||
return "Column";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual Variant data( const ModelIndex& modelIndex, ModelRole role ) const {
|
||||
if ( role == ModelRole::Display ) {
|
||||
switch ( modelIndex.column() ) {
|
||||
case 0:
|
||||
return Variant( String::toString( mStack.stackFrames[modelIndex.row()].id ) );
|
||||
case 1:
|
||||
return Variant( mStack.stackFrames[modelIndex.row()].name.c_str() );
|
||||
case 2:
|
||||
return mStack.stackFrames[modelIndex.row()].source
|
||||
? Variant( mStack.stackFrames[modelIndex.row()].source->name )
|
||||
: Variant();
|
||||
case 3:
|
||||
return mStack.stackFrames[modelIndex.row()].source
|
||||
? Variant( mStack.stackFrames[modelIndex.row()].source->path )
|
||||
: Variant();
|
||||
case 4:
|
||||
return Variant( String::toString( mStack.stackFrames[modelIndex.row()].line ) );
|
||||
case 5:
|
||||
return Variant(
|
||||
String::toString( mStack.stackFrames[modelIndex.row()].column ) );
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
protected:
|
||||
StackTraceInfo mStack;
|
||||
};
|
||||
|
||||
void DebuggerClientListener::stackTrace( const int /*threadId*/, const StackTraceInfo& stack ) {
|
||||
// if ( !stack.stackFrames.empty() ) {
|
||||
// mClient->scopes( stack.stackFrames[0].id );
|
||||
// }
|
||||
getStatusDebuggerController()->getUIStack()->setModel( std::make_shared<StackModel>( stack ) );
|
||||
|
||||
if ( !stack.stackFrames.empty() ) {
|
||||
mClient->scopes( stack.stackFrames[0].id );
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerClientListener::scopes( const int /*frameId**/, const std::vector<Scope>& scopes ) {
|
||||
@@ -106,4 +199,15 @@ void DebuggerClientListener::expressionEvaluated( const std::string& /*expressio
|
||||
void DebuggerClientListener::gotoTargets( const Source& /*source*/, const int /*line*/,
|
||||
const std::vector<GotoTarget>& /*targets*/ ) {}
|
||||
|
||||
StatusDebuggerController* DebuggerClientListener::getStatusDebuggerController() const {
|
||||
|
||||
auto debuggerElement =
|
||||
mPlugin->getManager()->getPluginContext()->getStatusBar()->getStatusBarElement(
|
||||
"status_app_debugger" );
|
||||
|
||||
if ( !debuggerElement )
|
||||
return nullptr;
|
||||
return static_cast<StatusDebuggerController*>( debuggerElement.get() );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "debuggerclient.hpp"
|
||||
#include "statusdebuggercontroller.hpp"
|
||||
|
||||
namespace ecode {
|
||||
|
||||
@@ -44,6 +45,8 @@ class DebuggerClientListener : public DebuggerClient::Listener {
|
||||
protected:
|
||||
DebuggerClient* mClient{ nullptr };
|
||||
DebuggerPlugin* mPlugin{ nullptr };
|
||||
|
||||
StatusDebuggerController* getStatusDebuggerController() const;
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -450,11 +450,11 @@ bool DebuggerPlugin::onLineNumberClick( UICodeEditor* editor, Uint32 lineNumber
|
||||
return false;
|
||||
Lock l( mBreakpointsMutex );
|
||||
auto& breakpoints = mBreakpoints[editor->getDocument().getFilePath()];
|
||||
auto breakpointIt = breakpoints.find( SourceBreakpoint( lineNumber ) );
|
||||
auto breakpointIt = breakpoints.find( SourceBreakpointStateful( lineNumber ) );
|
||||
if ( breakpointIt != breakpoints.end() ) {
|
||||
breakpoints.erase( breakpointIt );
|
||||
} else {
|
||||
breakpoints.insert( SourceBreakpoint( lineNumber ) );
|
||||
breakpoints.insert( SourceBreakpointStateful( lineNumber ) );
|
||||
}
|
||||
editor->invalidateDraw();
|
||||
return true;
|
||||
|
||||
@@ -64,7 +64,7 @@ class DebuggerPlugin : public PluginBase {
|
||||
UIDropDownList* mUIDebuggerList{ nullptr };
|
||||
UIDropDownList* mUIDebuggerConfList{ nullptr };
|
||||
UIPushButton* mRunButton{ nullptr };
|
||||
UnorderedMap<std::string, UnorderedSet<SourceBreakpoint>> mBreakpoints;
|
||||
UnorderedMap<std::string, UnorderedSet<SourceBreakpointStateful>> mBreakpoints;
|
||||
Mutex mBreakpointsMutex;
|
||||
|
||||
DebuggerPlugin( PluginManager* pluginManager, bool sync );
|
||||
|
||||
@@ -18,12 +18,30 @@ UIWidget* StatusDebuggerController::createWidget() {
|
||||
return mContainer;
|
||||
}
|
||||
|
||||
UITableView* StatusDebuggerController::getUIThreads() {
|
||||
return mUIThreads;
|
||||
}
|
||||
|
||||
UITableView* StatusDebuggerController::getUIStack() {
|
||||
return mUIStack;
|
||||
}
|
||||
|
||||
UITableView* StatusDebuggerController::getUIBreakpoints() {
|
||||
return mUIBreakpoints;
|
||||
}
|
||||
|
||||
void StatusDebuggerController::createContainer() {
|
||||
if ( mContainer )
|
||||
return;
|
||||
const auto XML = R"xml(
|
||||
<hbox id="app_debugger" lw="mp" lh="mp" visible="false">
|
||||
</hbox>
|
||||
<TabWidget layout_width="match_parent" layout_height="0dp" layout_weight="1">
|
||||
<TableView id="debugger_stack" layout_width="mp" layout_height="mp" />
|
||||
<TableView id="debugger_threads" layout_width="mp" layout_height="mp" />
|
||||
<TableView id="debugger_breakpoints" layout_width="mp" layout_height="mp" />
|
||||
<Tab text="@string(stack, Stack)" owns="debugger_stack" />
|
||||
<Tab text="@string(threads, Threads)" owns="debugger_threads" />
|
||||
<Tab text="@string(breakpoints, Breakpoints)" owns="debugger_breakpoints" />
|
||||
</TabWidget>
|
||||
)xml";
|
||||
|
||||
if ( mMainSplitter->getLastWidget() != nullptr ) {
|
||||
@@ -34,6 +52,10 @@ void StatusDebuggerController::createContainer() {
|
||||
mContainer = mContext->getUISceneNode()
|
||||
->loadLayoutFromString( XML, mMainSplitter )
|
||||
->asType<UILinearLayout>();
|
||||
|
||||
mContainer->bind( "debugger_threads", mUIThreads );
|
||||
mContainer->bind( "debugger_stack", mUIStack );
|
||||
mContainer->bind( "debugger_breakpoints", mUIBreakpoints );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -27,8 +27,17 @@ class StatusDebuggerController : public StatusBarElement {
|
||||
|
||||
UIWidget* createWidget();
|
||||
|
||||
UITableView* getUIThreads();
|
||||
|
||||
UITableView* getUIStack();
|
||||
|
||||
UITableView* getUIBreakpoints();
|
||||
|
||||
protected:
|
||||
UILinearLayout* mContainer{ nullptr };
|
||||
UITableView* mUIThreads{ nullptr };
|
||||
UITableView* mUIStack{ nullptr };
|
||||
UITableView* mUIBreakpoints{ nullptr };
|
||||
|
||||
void createContainer();
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "uistatusbar.hpp"
|
||||
#include "globalsearchcontroller.hpp"
|
||||
#include "plugins/plugincontextprovider.hpp"
|
||||
#include "statusappoutputcontroller.hpp"
|
||||
#include "statusbuildoutputcontroller.hpp"
|
||||
#include "statusterminalcontroller.hpp"
|
||||
#include "uistatusbar.hpp"
|
||||
#include "universallocator.hpp"
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
#include <eepp/window/window.hpp>
|
||||
@@ -160,6 +160,13 @@ void UIStatusBar::setPluginContextProvider( PluginContextProvider* app ) {
|
||||
updateState();
|
||||
}
|
||||
|
||||
std::shared_ptr<StatusBarElement> UIStatusBar::getStatusBarElement( const std::string& id ) const {
|
||||
auto elemIt = mElements.find( id );
|
||||
if ( elemIt != mElements.end() )
|
||||
return elemIt->second.second;
|
||||
return {};
|
||||
}
|
||||
|
||||
void UIStatusBar::onVisibilityChange() {
|
||||
UILinearLayout::onVisibilityChange();
|
||||
if ( isVisible() )
|
||||
|
||||
@@ -51,6 +51,8 @@ class UIStatusBar : public UILinearLayout, public WidgetCommandExecuter {
|
||||
|
||||
void setPluginContextProvider( PluginContextProvider* app );
|
||||
|
||||
std::shared_ptr<StatusBarElement> getStatusBarElement( const std::string& id ) const;
|
||||
|
||||
protected:
|
||||
UnorderedMap<std::string, std::pair<UIPushButton*, std::shared_ptr<StatusBarElement>>>
|
||||
mElements;
|
||||
|
||||
Reference in New Issue
Block a user