From 7d2fbc4678bfe3226ca9a113e193a5001b38b8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Fri, 27 Oct 2023 01:55:43 -0300 Subject: [PATCH] ecode: Fix improper lock when adding watches. Fixed several crashed when plugin events where fired from closed editors. --- include/eepp/scene/node.hpp | 3 + include/eepp/ui/doc/textdocument.hpp | 58 +++++++------ include/eepp/ui/widgetcommandexecuter.hpp | 1 - src/eepp/scene/node.cpp | 6 ++ src/eepp/ui/doc/textdocument.cpp | 27 ++++-- src/eepp/ui/uicodeeditor.cpp | 4 +- src/thirdparty/efsw | 2 +- src/tools/ecode/ecode.cpp | 68 +++++++++------ src/tools/ecode/ecode.hpp | 4 +- src/tools/ecode/notificationcenter.cpp | 86 +++++++++++-------- src/tools/ecode/notificationcenter.hpp | 6 +- .../plugins/formatter/formatterplugin.cpp | 11 ++- .../ecode/plugins/linter/linterplugin.cpp | 18 ++-- .../ecode/plugins/lsp/lspclientplugin.cpp | 66 ++++++++------ 14 files changed, 220 insertions(+), 140 deletions(-) diff --git a/include/eepp/scene/node.hpp b/include/eepp/scene/node.hpp index a2f170b4e..276034ff2 100644 --- a/include/eepp/scene/node.hpp +++ b/include/eepp/scene/node.hpp @@ -394,6 +394,9 @@ class EE_API Node : public Transformable { void setTimeout( Actions::Runnable::RunnableFunc runnable, const Time& delay = Seconds( 0 ), const Uint32& uniqueIdentifier = 0 ); + void debounce( Actions::Runnable::RunnableFunc runnable, const Time& delay, + const Uint32& uniqueIdentifier ); + void setInterval( Actions::Runnable::RunnableFunc runnable, const Time& interval, const Uint32& uniqueIdentifier = 0 ); diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index fb5f492a5..672f92bc4 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include using namespace EE::System; @@ -36,8 +34,6 @@ struct DocumentContentChange { class EE_API TextDocument { public: - typedef std::function DocumentCommand; - enum class UndoRedo { Undo, Redo }; enum class IndentType { IndentSpaces, IndentTabs }; @@ -50,26 +46,6 @@ class EE_API TextDocument { enum class MatchDirection { Forward, Backward }; - static std::string lineEndingToString( const LineEnding& le ) { - switch ( le ) { - case LineEnding::CRLF: - return "CRLF"; - case LineEnding::CR: - return "CR"; - case LineEnding::LF: - default: - return "LF"; - } - } - - static LineEnding stringToLineEnding( const std::string& str ) { - if ( "CR" == str ) - return LineEnding::CR; - if ( "CRLF" == str ) - return LineEnding::CRLF; - return LineEnding::LF; - } - class EE_API Client { public: virtual ~Client(); @@ -95,6 +71,29 @@ class EE_API TextDocument { virtual TextRange getVisibleRange() const { return {}; }; }; + typedef std::function DocumentCommand; + typedef std::function DocumentRefCommand; + + static std::string lineEndingToString( const LineEnding& le ) { + switch ( le ) { + case LineEnding::CRLF: + return "CRLF"; + case LineEnding::CR: + return "CR"; + case LineEnding::LF: + default: + return "LF"; + } + } + + static LineEnding stringToLineEnding( const std::string& str ) { + if ( "CR" == str ) + return LineEnding::CR; + if ( "CRLF" == str ) + return LineEnding::CRLF; + return LineEnding::LF; + } + TextDocument( bool verbose = true ); ~TextDocument(); @@ -349,10 +348,14 @@ class EE_API TextDocument { void execute( const std::string& command ); - void setCommands( const std::map& cmds ); + void execute( const std::string& command, Client* client ); + + void setCommands( const UnorderedMap& cmds ); void setCommand( const std::string& command, const DocumentCommand& func ); + void setCommand( const std::string& command, const DocumentRefCommand& func ); + bool hasCommand( const std::string& command ); bool removeCommand( const std::string& command ); @@ -629,7 +632,8 @@ class EE_API TextDocument { std::string mDefaultFileName; Uint64 mCleanChangeId; Uint32 mPageSize{ 10 }; - std::map mCommands; + UnorderedMap mCommands; + UnorderedMap mRefCommands; String mNonWordChars; Client* mActiveClient{ nullptr }; mutable Mutex mLoadingMutex; @@ -637,7 +641,7 @@ class EE_API TextDocument { size_t mLastSelection{ 0 }; std::unique_ptr mHighlighter; Mutex mStopFlagsMutex; - std::unordered_map> mStopFlags; + UnorderedMap> mStopFlags; void initializeCommands(); diff --git a/include/eepp/ui/widgetcommandexecuter.hpp b/include/eepp/ui/widgetcommandexecuter.hpp index 50701be56..08b1a471f 100644 --- a/include/eepp/ui/widgetcommandexecuter.hpp +++ b/include/eepp/ui/widgetcommandexecuter.hpp @@ -4,7 +4,6 @@ #include #include #include -#include using namespace EE::Scene; diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index 8dd544fea..f36e1c378 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -1543,6 +1543,12 @@ void Node::setTimeout( Actions::Runnable::RunnableFunc runnable, const Time& del runAction( action ); } +void Node::debounce( Actions::Runnable::RunnableFunc runnable, const Time& delay, + const Uint32& uniqueIdentifier ) { + removeActionsByTag( uniqueIdentifier ); + setTimeout( std::move( runnable ), std::move( delay ), uniqueIdentifier ); +} + void Node::setInterval( Actions::Runnable::RunnableFunc runnable, const Time& interval, const Uint32& uniqueIdentifier ) { Action* action = Actions::Runnable::New( std::move( runnable ), interval, true ); diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 44fb89065..09ce8597a 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include #include #include @@ -2083,12 +2082,20 @@ bool TextDocument::isDirty() const { void TextDocument::execute( const std::string& command ) { auto cmdIt = mCommands.find( command ); - if ( cmdIt != mCommands.end() ) { + if ( cmdIt != mCommands.end() ) cmdIt->second(); - } } -void TextDocument::setCommands( const std::map& cmds ) { +void TextDocument::execute( const std::string& command, Client* client ) { + auto cmdIt = mCommands.find( command ); + if ( cmdIt != mCommands.end() ) + return cmdIt->second(); + auto cmdRefIt = mRefCommands.find( command ); + if ( cmdRefIt != mRefCommands.end() ) + return cmdRefIt->second( client ); +} + +void TextDocument::setCommands( const UnorderedMap& cmds ) { mCommands.insert( cmds.begin(), cmds.end() ); } @@ -2097,12 +2104,18 @@ void TextDocument::setCommand( const std::string& command, mCommands[command] = func; } +void TextDocument::setCommand( const std::string& command, + const TextDocument::DocumentRefCommand& func ) { + mRefCommands[command] = func; +} + bool TextDocument::hasCommand( const std::string& command ) { - return mCommands.find( command ) != mCommands.end(); + return mCommands.find( command ) != mCommands.end() || + mRefCommands.find( command ) != mRefCommands.end(); } bool TextDocument::removeCommand( const std::string& command ) { - return mCommands.erase( command ) > 0; + return mCommands.erase( command ) > 0 || mRefCommands.erase( command ) > 0; } static std::pair findType( const String& str, const String& findStr, diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 7ea43e912..148d47f78 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -927,7 +927,7 @@ Uint32 UICodeEditor::onKeyDown( const KeyEvent& event ) { if ( !cmd.empty() ) { // Allow copy selection on locked mode if ( !mLocked || mUnlockedCmd.find( cmd ) != mUnlockedCmd.end() ) { - mDoc->execute( cmd ); + mDoc->execute( cmd, this ); mLastExecuteEventId = getUISceneNode()->getWindow()->getInput()->getEventsSentId(); return 1; } @@ -1060,7 +1060,7 @@ bool UICodeEditor::onCreateContextMenu( const Vector2i& position, const Uint32& return; UIMenuItem* item = event->getNode()->asType(); std::string txt( item->getId() ); - mDoc.get()->execute( txt ); + mDoc.get()->execute( txt, this ); menu->hide(); } ); diff --git a/src/thirdparty/efsw b/src/thirdparty/efsw index 34334377a..2445f5526 160000 --- a/src/thirdparty/efsw +++ b/src/thirdparty/efsw @@ -1 +1 @@ -Subproject commit 34334377a8579048abfb71a01900dca1b7bd0da2 +Subproject commit 2445f5526812d2aa6fb198c41ba8a928db249bb6 diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 0d8786a27..fe317d44a 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -395,7 +395,8 @@ UIFileDialog* App::saveFileDialog( UICodeEditor* editor, bool focusOnClose ) { void App::runCommand( const std::string& command ) { if ( mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_CODEEDITOR ) ) { - mSplitter->getCurWidget()->asType()->getDocument().execute( command ); + UICodeEditor* editor = mSplitter->getCurWidget()->asType(); + editor->getDocument().execute( command, editor ); } else if ( mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { mSplitter->getCurWidget()->asType()->execute( command ); @@ -523,7 +524,7 @@ bool App::trySendUnlockedCmd( const KeyEvent& keyEvent ) { std::string cmd = mSplitter->getCurEditor()->getKeyBindings().getCommandFromKeyBind( { keyEvent.getKeyCode(), keyEvent.getMod() } ); if ( !cmd.empty() && mSplitter->getCurEditor()->isUnlockedCommand( cmd ) ) { - mSplitter->getCurEditor()->getDocument().execute( cmd ); + mSplitter->getCurEditor()->getDocument().execute( cmd, mSplitter->getCurEditor() ); return true; } } else if ( mSplitter->getCurWidget() != nullptr && @@ -1741,6 +1742,14 @@ void App::setTheme( const std::string& path ) { mUISceneNode->reloadStyle( true, true ); } +bool App::dirInFolderWatches( const std::string& dir ) { + Lock l( mWatchesLock ); + for ( const auto& watch : mFolderWatches ) + if ( String::startsWith( dir, watch.first ) ) + return true; + return false; +} + void App::onRealDocumentLoaded( UICodeEditor* editor, const std::string& path ) { updateEditorTitle( editor ); if ( mSplitter->curEditorExistsAndFocused() && editor == mSplitter->getCurEditor() ) @@ -1753,7 +1762,8 @@ void App::onRealDocumentLoaded( UICodeEditor* editor, const std::string& path ) if ( mRecentFiles.size() > 10 ) mRecentFiles.resize( 10 ); cleanUpRecentFiles(); - updateRecentFiles(); + auto urfId = String::hash( "updateRecentFiles" ); + mUISceneNode->debounce( [this] { updateRecentFiles(); }, Seconds( 0.5f ), urfId ); if ( mSplitter->curEditorExistsAndFocused() && mSplitter->getCurEditor() == editor ) { mSettings->updateDocumentMenu(); updateDocInfo( editor->getDocument() ); @@ -1769,9 +1779,13 @@ void App::onRealDocumentLoaded( UICodeEditor* editor, const std::string& path ) if ( mFileWatcher && doc.hasFilepath() && ( !mDirTree || !mDirTree->isDirInTree( doc.getFileInfo().getFilepath() ) ) ) { std::string dir( FileSystem::fileRemoveFileName( doc.getFileInfo().getFilepath() ) ); - Lock l( mWatchesLock ); - if ( mFileWatcher ) - mFilesFolderWatches[dir] = mFileWatcher->addWatch( dir, mFileSystemListener ); + mThreadPool->run( [this, dir] { + if ( mFileWatcher && !dirInFolderWatches( dir ) ) { + auto watchId = mFileWatcher->addWatch( dir, mFileSystemListener ); + Lock l( mWatchesLock ); + mFilesFolderWatches[dir] = watchId; + } + } ); } } @@ -2387,9 +2401,8 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { Lock l( mWatchesLock ); auto itWatch = mFilesFolderWatches.find( dir ); if ( mFileWatcher && itWatch != mFilesFolderWatches.end() ) { - if ( !mDirTree || !mDirTree->isDirInTree( dir ) ) { + if ( !mDirTree || !mDirTree->isDirInTree( dir ) ) mFileWatcher->removeWatch( itWatch->second ); - } mFilesFolderWatches.erase( itWatch ); } } ); @@ -2436,9 +2449,11 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { auto docLoaded = [this, editor, docChanged]( const Event* event ) { if ( editor->getDocument().getFileInfo().getExtension() == "svg" ) { - editor->getDocument().setCommand( "show-image-preview", [this, editor]() { - loadImageFromMemory( editor->getDocument().getText().toUtf8() ); - } ); + editor->getDocument().setCommand( + "show-image-preview", [this]( TextDocument::Client* client ) { + loadImageFromMemory( + static_cast( client )->getDocument().getText().toUtf8() ); + } ); editor->on( Event::OnCreateContextMenu, [this]( const Event* event ) { auto cevent = static_cast( event ); cevent->getMenu() @@ -2507,19 +2522,22 @@ void App::updateEditorState() { } void App::removeFolderWatches() { - std::unordered_set folderWatches; + std::unordered_map folderWatches; std::unordered_map filesFolderWatches; - Lock l( mWatchesLock ); if ( !mFileWatcher ) return; - folderWatches = mFolderWatches; - filesFolderWatches = mFilesFolderWatches; - mFolderWatches.clear(); - mFilesFolderWatches.clear(); + + { + Lock l( mWatchesLock ); + folderWatches = mFolderWatches; + filesFolderWatches = mFilesFolderWatches; + mFolderWatches.clear(); + mFilesFolderWatches.clear(); + } for ( const auto& dir : folderWatches ) - mFileWatcher->removeWatch( dir ); + mFileWatcher->removeWatch( dir.first ); for ( const auto& fileFolder : filesFolderWatches ) mFileWatcher->removeWatch( fileFolder.second ); @@ -2542,11 +2560,13 @@ void App::loadDirTree( const std::string& path ) { syncProjectTreeWithEditor( mSplitter->getCurEditor() ); } ); removeFolderWatches(); - { - Lock l( mWatchesLock ); - if ( mFileWatcher ) - mFolderWatches.insert( - mFileWatcher->addWatch( dirTree.getPath(), mFileSystemListener, true ) ); + if ( mFileWatcher ) { + { + Lock l( mWatchesLock ); + mFolderWatches.insert( { dirTree.getPath(), 0 } ); + } + mFolderWatches[dirTree.getPath()] = + mFileWatcher->addWatch( dirTree.getPath(), mFileSystemListener, true ); } mFileSystemListener->setDirTree( mDirTree ); }, @@ -2900,7 +2920,7 @@ void App::initProjectTreeView( std::string path, bool openClean ) { std::string cmd = mSplitter->getCurEditor()->getKeyBindings().getCommandFromKeyBind( { keyEvent->getKeyCode(), keyEvent->getMod() } ); if ( !cmd.empty() && mSplitter->getCurEditor()->isUnlockedCommand( cmd ) ) { - mSplitter->getCurEditor()->getDocument().execute( cmd ); + mSplitter->getCurEditor()->getDocument().execute( cmd, mSplitter->getCurEditor() ); return 1; } } diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 9cf8bbe3d..f2a5e991d 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -483,7 +483,7 @@ class App : public UICodeEditorSplitter::Client { efsw::FileWatcher* mFileWatcher{ nullptr }; FileSystemListener* mFileSystemListener{ nullptr }; Mutex mWatchesLock; - std::unordered_set mFolderWatches; + std::unordered_map mFolderWatches; std::unordered_map mFilesFolderWatches; std::unique_ptr mGlobalSearchController; std::unique_ptr mDocSearchController; @@ -594,6 +594,8 @@ class App : public UICodeEditorSplitter::Client { void updateDocInfoLocation(); void onReady(); + + bool dirInFolderWatches( const std::string& dir ); }; } // namespace ecode diff --git a/src/tools/ecode/notificationcenter.cpp b/src/tools/ecode/notificationcenter.cpp index 65fea80db..c7abaa15b 100644 --- a/src/tools/ecode/notificationcenter.cpp +++ b/src/tools/ecode/notificationcenter.cpp @@ -23,28 +23,35 @@ NotificationCenter::NotificationCenter( UILayout* layout, PluginManager* pluginM } ); } -UITextView* NotificationCenter::addNotification( const String& text, const Time& delay ) { - UITextView* tv = UITextView::New(); - tv->addEventListener( Event::MouseClick, [tv]( const Event* event ) { - const MouseEvent* mouseEvent = static_cast( event ); - if ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) - tv->close(); - } ); - tv->setParent( mLayout ); - tv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); - tv->setFlags( UI_WORD_WRAP ); - tv->setText( text ); - tv->addClass( "notification" ); - Action* sequence = Actions::Sequence::New( - { Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ), - Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } ); - tv->runAction( sequence ); - return tv; +void NotificationCenter::addNotification( const String& text, const Time& delay ) { + auto action = [this, text, delay]() { + UITextView* tv = UITextView::New(); + tv->addEventListener( Event::MouseClick, [tv]( const Event* event ) { + const MouseEvent* mouseEvent = static_cast( event ); + if ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) + tv->close(); + } ); + tv->setParent( mLayout ); + tv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); + tv->setFlags( UI_WORD_WRAP ); + tv->setText( text ); + tv->addClass( "notification" ); + Action* sequence = Actions::Sequence::New( + { Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ), + Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } ); + tv->runAction( sequence ); + }; + + if ( Engine::isRunninMainThread() ) + action(); + else + mLayout->runOnMainThread( action ); } -UILinearLayout* NotificationCenter::addShowRequest( const String& uri, const String& actionText, - const Time& delay ) { - static const auto layout = R"xml( +void NotificationCenter::addShowRequest( const String& uri, const String& actionText, + const Time& delay ) { + auto action = [this, uri, actionText, delay]() { + static const auto layout = R"xml( @@ -52,23 +59,28 @@ UILinearLayout* NotificationCenter::addShowRequest( const String& uri, const Str )xml"; - UILinearLayout* lay = mLayout->getUISceneNode() - ->loadLayoutFromString( layout, mLayout ) - ->asType(); - UITextView* tv = lay->findByType( UI_TYPE_TEXTVIEW )->asType(); - tv->setText( mLayout->getUISceneNode()->i18n( - "open_url_question", String::format( "Open URL\n%s?", uri.toUtf8().c_str() ) ) ); - UIPushButton* pb = lay->findByType( UI_TYPE_PUSHBUTTON )->asType(); - pb->setText( actionText ); - pb->on( Event::MouseClick, [uri]( const Event* event ) { - if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) - Engine::instance()->openURI( uri ); - } ); - Action* sequence = Actions::Sequence::New( - { Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ), - Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } ); - lay->runAction( sequence ); - return lay; + UILinearLayout* lay = mLayout->getUISceneNode() + ->loadLayoutFromString( layout, mLayout ) + ->asType(); + UITextView* tv = lay->findByType( UI_TYPE_TEXTVIEW )->asType(); + tv->setText( mLayout->getUISceneNode()->i18n( + "open_url_question", String::format( "Open URL\n%s?", uri.toUtf8().c_str() ) ) ); + UIPushButton* pb = lay->findByType( UI_TYPE_PUSHBUTTON )->asType(); + pb->setText( actionText ); + pb->on( Event::MouseClick, [uri]( const Event* event ) { + if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) + Engine::instance()->openURI( uri ); + } ); + Action* sequence = Actions::Sequence::New( + { Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ), + Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } ); + lay->runAction( sequence ); + }; + + if ( Engine::isRunninMainThread() ) + action(); + else + mLayout->runOnMainThread( action ); } } // namespace ecode diff --git a/src/tools/ecode/notificationcenter.hpp b/src/tools/ecode/notificationcenter.hpp index 866f88c00..218fc1435 100644 --- a/src/tools/ecode/notificationcenter.hpp +++ b/src/tools/ecode/notificationcenter.hpp @@ -10,10 +10,10 @@ class NotificationCenter { public: NotificationCenter( UILayout* layout, PluginManager* pluginManager ); - UITextView* addNotification( const String& text, const Time& delay = Seconds( 2.5 ) ); + void addNotification( const String& text, const Time& delay = Seconds( 2.5 ) ); - UILinearLayout* addShowRequest( const String& uri, const String& actionText, - const Time& delay = Seconds( 2.5 ) ); + void addShowRequest( const String& uri, const String& actionText, + const Time& delay = Seconds( 2.5 ) ); protected: UILayout* mLayout{ nullptr }; diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.cpp b/src/tools/ecode/plugins/formatter/formatterplugin.cpp index 40e3a54ef..954a6ac0f 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.cpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.cpp @@ -72,16 +72,19 @@ void FormatterPlugin::onRegister( UICodeEditor* editor ) { editor->getKeyBindings().addKeybindString( kb.second, kb.first ); } - if ( editor->hasDocument() ) - editor->getDocument().setCommand( "format-doc", [&, editor]() { formatDoc( editor ); } ); + if ( editor->hasDocument() ) { + editor->getDocument().setCommand( "format-doc", [this]( TextDocument::Client* client ) { + formatDoc( static_cast( client ) ); + } ); + } listeners.push_back( - editor->addEventListener( Event::OnDocumentLoaded, [&, editor]( const Event* ) { + editor->addEventListener( Event::OnDocumentLoaded, [this, editor]( const Event* ) { tryRequestCapabilities( editor->getDocumentRef() ); } ) ); listeners.push_back( - editor->addEventListener( Event::OnDocumentChanged, [&, editor]( const Event* ) { + editor->addEventListener( Event::OnDocumentChanged, [this, editor]( const Event* ) { TextDocument* newDoc = editor->getDocumentRef().get(); mEditorDocs[editor] = newDoc; } ) ); diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 11781dcde..1d94679b9 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -13,7 +13,6 @@ #include #include #include -#include using json = nlohmann::json; @@ -627,13 +626,20 @@ void LinterPlugin::onRegister( UICodeEditor* editor ) { if ( editor->hasDocument() ) { auto& doc = editor->getDocument(); - doc.setCommand( "linter-go-to-next-error", [this, editor] { goToNextError( editor ); } ); + doc.setCommand( "linter-go-to-next-error", [this]( TextDocument::Client* client ) { + goToNextError( static_cast( client ) ); + } ); - doc.setCommand( "linter-go-to-previous-error", - [this, editor] { goToPrevError( editor ); } ); + doc.setCommand( "linter-go-to-previous-error", [this]( TextDocument::Client* client ) { + goToPrevError( static_cast( client ) ); + } ); - doc.setCommand( "linter-copy-error-message", [this, editor] { - editor->getUISceneNode()->getWindow()->getClipboard()->setText( mErrorMsg ); + doc.setCommand( "linter-copy-error-message", [this]( TextDocument::Client* client ) { + static_cast( client ) + ->getUISceneNode() + ->getWindow() + ->getClipboard() + ->setText( mErrorMsg ); } ); } diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index 7ae9a89f7..95e45249f 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -447,7 +447,7 @@ bool LSPClientPlugin::onMouseClick( UICodeEditor* editor, const Vector2i& pos, if ( !docPos.isValid() || !editor->getDocument().isValidPosition( docPos ) ) return false; - editor->getDocument().execute( "lsp-go-to-definition" ); + editor->getDocument().execute( "lsp-go-to-definition", editor ); return true; } @@ -1144,46 +1144,58 @@ void LSPClientPlugin::onRegister( UICodeEditor* editor ) { if ( editor->hasDocument() ) { auto& doc = editor->getDocument(); - doc.setCommand( "lsp-go-to-definition", [this, editor]() { - getAndGoToLocation( editor, "textDocument/definition" ); + doc.setCommand( "lsp-go-to-definition", [this]( TextDocument::Client* client ) { + getAndGoToLocation( static_cast( client ), "textDocument/definition" ); } ); - doc.setCommand( "lsp-rename-symbol-under-cursor", - [this, editor]() { renameSymbol( editor ); } ); - - doc.setCommand( "lsp-go-to-declaration", [this, editor]() { - getAndGoToLocation( editor, "textDocument/declaration" ); + doc.setCommand( "lsp-rename-symbol-under-cursor", [this]( TextDocument::Client* client ) { + renameSymbol( static_cast( client ) ); } ); - doc.setCommand( "lsp-go-to-implementation", [this, editor]() { - getAndGoToLocation( editor, "textDocument/implementation" ); + doc.setCommand( "lsp-go-to-declaration", [this]( TextDocument::Client* client ) { + getAndGoToLocation( static_cast( client ), "textDocument/declaration" ); } ); - doc.setCommand( "lsp-go-to-type-definition", [this, editor]() { - getAndGoToLocation( editor, "textDocument/typeDefinition" ); + doc.setCommand( "lsp-go-to-implementation", [this]( TextDocument::Client* client ) { + getAndGoToLocation( static_cast( client ), + "textDocument/implementation" ); } ); - doc.setCommand( "lsp-switch-header-source", - [this, editor]() { switchSourceHeader( editor ); } ); - - doc.setCommand( "lsp-symbol-info", [this, editor]() { getSymbolInfo( editor ); } ); - - doc.setCommand( "lsp-symbol-references", [this, editor] { - mClientManager.getSymbolReferences( editor->getDocumentRef() ); + doc.setCommand( "lsp-go-to-type-definition", [this]( TextDocument::Client* client ) { + getAndGoToLocation( static_cast( client ), + "textDocument/typeDefinition" ); } ); - doc.setCommand( "lsp-symbol-code-action", [this, editor] { codeAction( editor ); } ); - - doc.setCommand( "lsp-memory-usage", [this, editor] { - mClientManager.memoryUsage( editor->getDocumentRef() ); + doc.setCommand( "lsp-switch-header-source", [this]( TextDocument::Client* client ) { + switchSourceHeader( static_cast( client ) ); } ); - doc.setCommand( "lsp-refresh-semantic-highlighting", [this, editor] { - mClientManager.requestSymanticHighlighting( editor->getDocumentRef() ); + doc.setCommand( "lsp-symbol-info", [this]( TextDocument::Client* client ) { + getSymbolInfo( static_cast( client ) ); } ); - doc.setCommand( "lsp-format-range", [this, editor] { - mClientManager.rangeFormatting( editor->getDocumentRef() ); + doc.setCommand( "lsp-symbol-references", [this]( TextDocument::Client* client ) { + mClientManager.getSymbolReferences( + static_cast( client )->getDocumentRef() ); + } ); + + doc.setCommand( "lsp-symbol-code-action", [this]( TextDocument::Client* client ) { + codeAction( static_cast( client ) ); + } ); + + doc.setCommand( "lsp-memory-usage", [this]( TextDocument::Client* client ) { + mClientManager.memoryUsage( static_cast( client )->getDocumentRef() ); + } ); + + doc.setCommand( "lsp-refresh-semantic-highlighting", + [this]( TextDocument::Client* client ) { + mClientManager.requestSymanticHighlighting( + static_cast( client )->getDocumentRef() ); + } ); + + doc.setCommand( "lsp-format-range", [this]( TextDocument::Client* client ) { + mClientManager.rangeFormatting( + static_cast( client )->getDocumentRef() ); } ); }