From 344d1c72f89e85a69cf9c8f452543b76d6783f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Thu, 2 Mar 2023 03:35:15 -0300 Subject: [PATCH] ecode: Improvements for the root path handling. Improvements for the workspace symbol search. --- src/eepp/ui/uicodeeditor.cpp | 2 +- .../ecode/plugins/lsp/lspclientplugin.cpp | 10 ++++- .../ecode/plugins/lsp/lspclientserver.cpp | 40 ++++++++++++++++--- .../ecode/plugins/lsp/lspclientserver.hpp | 9 ++++- .../plugins/lsp/lspclientservermanager.cpp | 14 ++++--- src/tools/ecode/plugins/lsp/lspprotocol.hpp | 3 ++ src/tools/ecode/universallocator.cpp | 7 +++- 7 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 20c484910..70188eae0 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -1422,7 +1422,7 @@ Float UICodeEditor::getLineWidth( const Int64& lineIndex ) { void UICodeEditor::updateScrollBar() { int notVisibleLineCount = (int)mDoc->linesCount() - (int)getViewPortLineCount().y; - if ( mLongestLineWidthDirty ) { + if ( mLongestLineWidthDirty && mFont && mFont->isMonospace() ) { updateLongestLineWidth(); } diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index c949dd7aa..7dc718806 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -259,10 +259,16 @@ PluginRequestHandle LSPClientPlugin::processWorkspaceSymbol( const PluginMessage if ( servers.empty() ) return {}; + std::string query = msg.asJSON().value( "query", "" ); for ( const auto server : servers ) { server->workspaceSymbol( - msg.asJSON().value( "query", "" ), - [&]( const PluginIDType& id, const LSPSymbolInformationList& info ) { + query, [&, query]( const PluginIDType& id, LSPSymbolInformationList&& info ) { + if ( !query.empty() ) { + for ( auto& i : info ) { + if ( i.score == 0.f ) + i.score = String::fuzzyMatch( i.name, query ); + } + } mManager->sendResponse( this, PluginMessageType::WorkspaceSymbol, PluginMessageFormat::SymbolInformation, &info, id ); } ); diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index 85272f1c4..899a3b0a7 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace ecode { @@ -313,6 +314,7 @@ static void fromJson( LSPServerCapabilities& caps, const json& json ) { fromJson( caps.completionProvider, json["completionProvider"] ); if ( json.contains( "signatureHelpProvider" ) ) fromJson( caps.signatureHelpProvider, json["signatureHelpProvider"] ); + caps.astProvider = toBoolOrObject( json, "astProvider" ); caps.definitionProvider = toBoolOrObject( json, "definitionProvider" ); caps.declarationProvider = toBoolOrObject( json, "declarationProvider" ); caps.typeDefinitionProvider = toBoolOrObject( json, "typeDefinitionProvider" ); @@ -957,6 +959,7 @@ void LSPClientServer::initialize() { json workspace; workspace["applyEdit"] = true; workspace["executeCommand"] = json{ { "dynamicRegistration", true } }; + workspace["workspaceFolders"] = true; json capabilities{ { "textDocument", @@ -1004,6 +1007,7 @@ void LSPClientServer::initialize() { params["rootUri"] = rootUri; params["workspaceFolders"] = toJson( { LSPWorkspaceFolder{ rootUri, FileSystem::fileNameFromPath( rootUri ) } } ); + mWorkspaceFolder = rootUri; write( newRequest( "initialize", params ), @@ -1085,6 +1089,11 @@ void LSPClientServer::notifyServerInitialized() { client.second->onServerInitialized(); } +bool LSPClientServer::needsAsync() { + return Engine::isEngineRunning() && + Engine::instance()->getMainThreadId() == Thread::getCurrentThreadId(); +} + bool LSPClientServer::isRunning() { return mProcess.isAlive() && !mProcess.isShootingDown(); } @@ -1147,9 +1156,6 @@ LSPClientServer::LSPRequestHandle LSPClientServer::write( const json& msg, method = msg[MEMBER_METHOD].get(); else if ( msg.contains( MEMBER_MESSAGE ) ) method = msg[MEMBER_MESSAGE]; - if ( method == "workspace/didChangeWorkspaceFolders" && - !mCapabilities.workspaceFolders.supported ) - return ret; Log::info( "LSPClientServer server %s calling %s", mLSP.name.c_str(), method.c_str() ); Log::debug( "LSPClientServer server %s sending message:\n%s", mLSP.name.c_str(), sjson.c_str() ); @@ -1161,8 +1167,16 @@ LSPClientServer::LSPRequestHandle LSPClientServer::write( const json& msg, return ret; } +void LSPClientServer::sendAsync( const json& msg, const JsonReplyHandler& h, + const JsonReplyHandler& eh ) { + getThreadPool()->run( [this, msg, h, eh] { send( msg, h, eh ); } ); +} + LSPClientServer::LSPRequestHandle LSPClientServer::send( const json& msg, const JsonReplyHandler& h, const JsonReplyHandler& eh ) { +#ifdef EE_DEBUG + // eeASSERT( !needsAsync() ); +#endif if ( mProcess.isAlive() ) { return write( msg, h, eh ); } else { @@ -1666,9 +1680,23 @@ LSPClientServer::LSPRequestHandle LSPClientServer::switchSourceHeader( const URI LSPClientServer::LSPRequestHandle LSPClientServer::didChangeWorkspaceFolders( const std::vector& added, - const std::vector& removed ) { - auto params = changeWorkspaceFoldersParams( added, removed ); - return send( newRequest( "workspace/didChangeWorkspaceFolders", params ) ); + const std::vector& removed, + bool async ) { + if ( mCapabilities.workspaceFolders.supported ) { + // Don't send the didChangeWorkspaceFolder if already in the same directory + if ( !added.empty() && mWorkspaceFolder == added[0].uri ) + return {}; + auto params = changeWorkspaceFoldersParams( added, removed ); + // Update CWD + if ( !added.empty() ) + mWorkspaceFolder = added[0].uri; + if ( async && needsAsync() ) { + sendAsync( newRequest( "workspace/didChangeWorkspaceFolders", params ) ); + return {}; + } + return send( newRequest( "workspace/didChangeWorkspaceFolders", params ) ); + } + return {}; } LSPClientServer::LSPRequestHandle LSPClientServer::documentCodeAction( diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.hpp b/src/tools/ecode/plugins/lsp/lspclientserver.hpp index 2322cbe0d..1be4312f5 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.hpp @@ -78,6 +78,9 @@ class LSPClientServer { LSPRequestHandle send( const json& msg, const JsonReplyHandler& h = nullptr, const JsonReplyHandler& eh = nullptr ); + void sendAsync( const json& msg, const JsonReplyHandler& h = nullptr, + const JsonReplyHandler& eh = nullptr ); + const LSPDefinition& getDefinition() const { return mLSP; } LSPRequestHandle documentSymbols( const URI& document, const JsonReplyHandler& h, @@ -123,7 +126,8 @@ class LSPClientServer { bool hasDocuments() const; LSPRequestHandle didChangeWorkspaceFolders( const std::vector& added, - const std::vector& removed ); + const std::vector& removed, + bool async ); void publishDiagnostics( const json& msg ); @@ -229,6 +233,7 @@ class LSPClientServer { std::string mReceive; std::string mReceiveErr; LSPServerCapabilities mCapabilities; + URI mWorkspaceFolder; struct DidChangeQueue { URI uri; @@ -258,6 +263,8 @@ class LSPClientServer { void goToLocation( const json& res ); void notifyServerInitialized(); + + bool needsAsync(); }; } // namespace ecode diff --git a/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp b/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp index d5e3f005f..936edd81f 100644 --- a/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp @@ -83,7 +83,8 @@ void LSPClientServerManager::tryRunServer( const std::shared_ptr& return; for ( const auto& lsp : lsps ) { - auto rootPath = findRootPath( lsp, doc ); + std::string rootPath = mLSPWorkspaceFolder.isEmpty() ? findRootPath( lsp, doc ) + : mLSPWorkspaceFolder.uri.getFSPath(); auto lspName = lsp.name.empty() ? lsp.command : lsp.name; String::HashType id = String::hash( lspName + "|" + lsp.language + "|" + rootPath ); LSPClientServer* server = nullptr; @@ -95,7 +96,7 @@ void LSPClientServerManager::tryRunServer( const std::shared_ptr& if ( ( server = serverUP.get() ) ) { mClients[id] = std::move( serverUP ); if ( !mLSPWorkspaceFolder.uri.empty() ) - server->didChangeWorkspaceFolders( { mLSPWorkspaceFolder }, {} ); + server->didChangeWorkspaceFolders( { mLSPWorkspaceFolder }, {}, true ); } } else { server = clientIt->second.get(); @@ -356,9 +357,8 @@ LSPDefinition LSPClientServerManager::getLSPForLang( const std::string& lang, const std::vector& extensions ) const { for ( const auto& lsp : mLSPs ) { - if ( lsp.language == lang ) { + if ( lsp.language == lang ) return lsp; - } if ( !lsp.filePatterns.empty() ) { for ( const auto& file : lsp.filePatterns ) { @@ -374,10 +374,14 @@ LSPClientServerManager::getLSPForLang( const std::string& lang, } void LSPClientServerManager::didChangeWorkspaceFolders( const std::string& folder ) { + std::vector oldLSPWorkspaceFolder; + if ( !mLSPWorkspaceFolder.isEmpty() ) + oldLSPWorkspaceFolder.emplace_back( mLSPWorkspaceFolder ); mLSPWorkspaceFolder = { "file://" + folder, FileSystem::fileNameFromPath( folder ) }; + std::vector newWorkspaceFolder = { mLSPWorkspaceFolder }; Lock l( mClientsMutex ); for ( auto& server : mClients ) - server.second->didChangeWorkspaceFolders( { mLSPWorkspaceFolder }, {} ); + server.second->didChangeWorkspaceFolders( newWorkspaceFolder, oldLSPWorkspaceFolder, true ); } const LSPWorkspaceFolder& LSPClientServerManager::getLSPWorkspaceFolder() const { diff --git a/src/tools/ecode/plugins/lsp/lspprotocol.hpp b/src/tools/ecode/plugins/lsp/lspprotocol.hpp index bcde27196..0b132c6a7 100644 --- a/src/tools/ecode/plugins/lsp/lspprotocol.hpp +++ b/src/tools/ecode/plugins/lsp/lspprotocol.hpp @@ -44,6 +44,8 @@ struct LSPLocation { struct LSPWorkspaceFolder { URI uri; std::string name; + + bool isEmpty() { return uri.empty(); } }; enum class LSPDocumentSyncKind { None = 0, Full = 1, Incremental = 2 }; @@ -91,6 +93,7 @@ struct LSPServerCapabilities { bool hoverProvider = false; LSPCompletionOptions completionProvider; LSPSignatureHelpOptions signatureHelpProvider; + bool astProvider = false; bool definitionProvider = false; // official extension as of 3.14.0 bool declarationProvider = false; diff --git a/src/tools/ecode/universallocator.cpp b/src/tools/ecode/universallocator.cpp index 550f3846e..dec453f2e 100644 --- a/src/tools/ecode/universallocator.cpp +++ b/src/tools/ecode/universallocator.cpp @@ -99,9 +99,10 @@ LSPSymbolInformationList fuzzyMatchTextDocumentSymbol( const LSPSymbolInformatio while ( matchesMap.size() > limit ) matchesMap.erase( std::prev( matchesMap.end() ) ); - for ( const auto& m : matchesMap ) + for ( auto& m : matchesMap ) { + m.second.score = m.first; nl.emplace_back( std::move( m.second ) ); - + } return nl; } @@ -462,6 +463,8 @@ void UniversalLocator::requestWorkspaceSymbol() { json j = json{ json{ "query", mWorkspaceSymbolQuery } }; mApp->getPluginManager()->sendRequest( PluginMessageType::WorkspaceSymbol, PluginMessageFormat::JSON, &j ); + } else if ( mWorkspaceSymbolModel && mWorkspaceSymbolModel.get() != mLocateTable->getModel() ) { + mLocateTable->setModel( mWorkspaceSymbolModel ); } }