mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-18 06:55:48 +03:00
ecode: Implemented LSP textDocument/references ("Find References to Symbol Under Cursor").
This commit is contained in:
@@ -306,7 +306,8 @@ void LSPClientPlugin::loadLSPConfig( std::vector<LSPDefinition>& lsps, const std
|
||||
auto& kb = j["keybindings"];
|
||||
auto list = { "lsp-go-to-definition", "lsp-go-to-declaration",
|
||||
"lsp-go-to-implementation", "lsp-go-to-type-definition",
|
||||
"lsp-switch-header-source", "lsp-symbol-info" };
|
||||
"lsp-switch-header-source", "lsp-symbol-info",
|
||||
"lsp-symbol-references" };
|
||||
for ( const auto& key : list ) {
|
||||
if ( kb.contains( key ) ) {
|
||||
if ( !kb[key].empty() )
|
||||
@@ -442,31 +443,36 @@ void LSPClientPlugin::onRegister( UICodeEditor* editor ) {
|
||||
}
|
||||
|
||||
if ( editor->hasDocument() ) {
|
||||
editor->getDocument().setCommand( "lsp-go-to-definition", [&, editor]() {
|
||||
auto& doc = editor->getDocument();
|
||||
|
||||
doc.setCommand( "lsp-go-to-definition", [&, editor]() {
|
||||
mClientManager.getAndGoToLocation( editor->getDocumentRef(),
|
||||
"textDocument/definition" );
|
||||
} );
|
||||
|
||||
editor->getDocument().setCommand( "lsp-go-to-declaration", [&, editor]() {
|
||||
doc.setCommand( "lsp-go-to-declaration", [&, editor]() {
|
||||
mClientManager.getAndGoToLocation( editor->getDocumentRef(),
|
||||
"textDocument/declaration" );
|
||||
} );
|
||||
|
||||
editor->getDocument().setCommand( "lsp-go-to-implementation", [&, editor]() {
|
||||
doc.setCommand( "lsp-go-to-implementation", [&, editor]() {
|
||||
mClientManager.getAndGoToLocation( editor->getDocumentRef(),
|
||||
"textDocument/implementation" );
|
||||
} );
|
||||
|
||||
editor->getDocument().setCommand( "lsp-go-to-type-definition", [&, editor]() {
|
||||
doc.setCommand( "lsp-go-to-type-definition", [&, editor]() {
|
||||
mClientManager.getAndGoToLocation( editor->getDocumentRef(),
|
||||
"textDocument/typeDefinition" );
|
||||
} );
|
||||
|
||||
editor->getDocument().setCommand( "lsp-switch-header-source",
|
||||
[&, editor]() { switchSourceHeader( editor ); } );
|
||||
doc.setCommand( "lsp-switch-header-source",
|
||||
[&, editor]() { switchSourceHeader( editor ); } );
|
||||
|
||||
editor->getDocument().setCommand( "lsp-symbol-info",
|
||||
[&, editor]() { getSymbolInfo( editor ); } );
|
||||
doc.setCommand( "lsp-symbol-info", [&, editor]() { getSymbolInfo( editor ); } );
|
||||
|
||||
doc.setCommand( "lsp-symbol-references", [&, editor] {
|
||||
mClientManager.getSymbolReferences( editor->getDocumentRef() );
|
||||
} );
|
||||
}
|
||||
|
||||
std::vector<Uint32> listeners;
|
||||
@@ -573,6 +579,9 @@ bool LSPClientPlugin::onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* me
|
||||
if ( cap.implementationProvider )
|
||||
addFn( "lsp-go-to-implementation", "Go To Implementation" );
|
||||
|
||||
if ( cap.referencesProvider )
|
||||
addFn( "lsp-symbol-references", "Find References to Symbol Under Cursor" );
|
||||
|
||||
if ( server->getDefinition().language == "cpp" || server->getDefinition().language == "c" )
|
||||
addFn( "lsp-switch-header-source", "Switch Header/Source" );
|
||||
|
||||
|
||||
@@ -168,12 +168,10 @@ static LSPLocation parseLocationLink( const json& loc ) {
|
||||
static std::vector<LSPLocation> parseDocumentLocation( const json& result ) {
|
||||
std::vector<LSPLocation> ret;
|
||||
if ( result.is_array() ) {
|
||||
const auto& locs = result;
|
||||
for ( const auto& def : locs ) {
|
||||
const auto& ob = def;
|
||||
ret.push_back( parseLocation( ob ) );
|
||||
for ( const auto& def : result ) {
|
||||
ret.push_back( parseLocation( def ) );
|
||||
if ( ret.back().uri.empty() )
|
||||
ret.back() = parseLocationLink( ob );
|
||||
ret.back() = parseLocationLink( def );
|
||||
}
|
||||
} else if ( result.is_object() ) {
|
||||
ret.push_back( parseLocation( result ) );
|
||||
@@ -197,7 +195,9 @@ static json textDocumentPositionParams( const URI& document, TextPosition pos )
|
||||
|
||||
static json referenceParams( const URI& document, TextPosition pos, bool decl ) {
|
||||
auto params = textDocumentPositionParams( document, pos );
|
||||
params["context"] = json{ { "includeDeclaration", decl } };
|
||||
json refCtx;
|
||||
refCtx["includeDeclaration"] = decl;
|
||||
params["context"] = refCtx;
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -301,6 +301,7 @@ static void fromJson( LSPServerCapabilities& caps, const json& json ) {
|
||||
caps.documentSymbolProvider = toBoolOrObject( json, "documentSymbolProvider" );
|
||||
caps.documentHighlightProvider = toBoolOrObject( json, "documentHighlightProvider" );
|
||||
caps.documentFormattingProvider = toBoolOrObject( json, "documentFormattingProvider" );
|
||||
caps.workspaceSymbolProvider = toBoolOrObject( json, "workspaceSymbolProvider" );
|
||||
if ( json.contains( "documentRangeFormattingProvider" ) )
|
||||
caps.documentRangeFormattingProvider =
|
||||
toBoolOrObject( json, "documentRangeFormattingProvider" );
|
||||
|
||||
@@ -149,6 +149,9 @@ class LSPClientServer {
|
||||
LSPRequestHandle documentReferences( const URI& document, const TextPosition& pos, bool decl,
|
||||
const JsonReplyHandler& h );
|
||||
|
||||
LSPRequestHandle documentReferences( const URI& document, const TextPosition& pos, bool decl,
|
||||
const LocationHandler& h );
|
||||
|
||||
LSPRequestHandle documentCompletion( const URI& document, const TextPosition& pos,
|
||||
const JsonReplyHandler& h );
|
||||
|
||||
@@ -187,10 +190,6 @@ class LSPClientServer {
|
||||
|
||||
void removeDoc( TextDocument* doc );
|
||||
|
||||
LSPClientServer::LSPRequestHandle documentReferences( const URI& document,
|
||||
const TextPosition& pos, bool decl,
|
||||
const LocationHandler& h );
|
||||
|
||||
protected:
|
||||
LSPClientServerManager* mManager{ nullptr };
|
||||
String::HashType mId;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lspclientservermanager.hpp"
|
||||
#include "../../projectsearch.hpp"
|
||||
#include "lspclientplugin.hpp"
|
||||
#include <algorithm>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
@@ -237,6 +238,47 @@ void LSPClientServerManager::setLSPDecayTime( const Time& lSPDecayTime ) {
|
||||
mLSPDecayTime = lSPDecayTime;
|
||||
}
|
||||
|
||||
void LSPClientServerManager::sendSymbolReferenceBroadcast( const std::vector<LSPLocation>& resp ) {
|
||||
if ( resp.empty() )
|
||||
return;
|
||||
|
||||
std::map<std::string, ProjectSearch::ResultData> res;
|
||||
|
||||
for ( auto& r : resp ) {
|
||||
auto& rd = res[r.uri.getPath()];
|
||||
if ( rd.file.empty() )
|
||||
rd.file = r.uri.getPath();
|
||||
auto curDoc = mPluginManager->getSplitter()->findDocFromPath( r.uri.getPath() );
|
||||
if ( !curDoc )
|
||||
continue;
|
||||
|
||||
ProjectSearch::ResultData::Result rs( curDoc->line( r.range.start().line() ).getText(),
|
||||
r.range, -1, -1 );
|
||||
|
||||
rd.results.emplace_back( std::move( rs ) );
|
||||
}
|
||||
|
||||
ProjectSearch::Result result;
|
||||
for ( auto& r : res ) {
|
||||
if ( !r.second.results.empty() )
|
||||
result.emplace_back( std::move( r.second ) );
|
||||
}
|
||||
|
||||
mPluginManager->sendBroadcast( PluginMessageType::SymbolReference,
|
||||
PluginMessageFormat::ProjectSearchResult, &result );
|
||||
}
|
||||
|
||||
void LSPClientServerManager::getSymbolReferences( std::shared_ptr<TextDocument> doc ) {
|
||||
auto* server = getOneLSPClientServer( doc );
|
||||
if ( !server )
|
||||
return;
|
||||
server->documentReferences(
|
||||
doc->getURI(), doc->getSelection().start(), true,
|
||||
[this]( const PluginIDType&, const std::vector<LSPLocation>& resp ) {
|
||||
sendSymbolReferenceBroadcast( resp );
|
||||
} );
|
||||
}
|
||||
|
||||
void LSPClientServerManager::didChangeWorkspaceFolders( const std::string& folder ) {
|
||||
mLSPWorkspaceFolder = { "file://" + folder, FileSystem::fileNameFromPath( folder ) };
|
||||
Lock l( mClientsMutex );
|
||||
|
||||
@@ -64,6 +64,8 @@ class LSPClientServerManager {
|
||||
|
||||
void setLSPDecayTime( const Time& lSPDecayTime );
|
||||
|
||||
void getSymbolReferences( std::shared_ptr<TextDocument> doc );
|
||||
|
||||
protected:
|
||||
friend class LSPClientServer;
|
||||
PluginManager* mPluginManager{ nullptr };
|
||||
@@ -89,6 +91,8 @@ class LSPClientServerManager {
|
||||
void closeLSPServer( const String::HashType& id );
|
||||
|
||||
void goToLocation( const LSPLocation& loc );
|
||||
|
||||
void sendSymbolReferenceBroadcast( const std::vector<LSPLocation>& resp );
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -101,6 +101,7 @@ struct LSPServerCapabilities {
|
||||
bool documentHighlightProvider = false;
|
||||
bool documentFormattingProvider = false;
|
||||
bool documentRangeFormattingProvider = false;
|
||||
bool workspaceSymbolProvider = false;
|
||||
LSPDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;
|
||||
bool renameProvider = false;
|
||||
// CodeActionOptions not useful/considered at present
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ECODE_PLUGINMANAGER_HPP
|
||||
#define ECODE_PLUGINMANAGER_HPP
|
||||
|
||||
#include "../projectsearch.hpp"
|
||||
#include "lsp/lspprotocol.hpp"
|
||||
#include <eepp/ui/models/model.hpp>
|
||||
#include <eepp/ui/tools/uicodeeditorsplitter.hpp>
|
||||
@@ -68,6 +69,7 @@ enum class PluginMessageType {
|
||||
CancelRequest, // Cancel a request ID
|
||||
FindAndOpenClosestURI, // Request a component to find and open the closest path from an URI
|
||||
DocumentFormatting, // Request the LSP Server to format a document
|
||||
SymbolReference, // Request the LSP Server to find a symbol reference in the project
|
||||
Undefined
|
||||
};
|
||||
|
||||
@@ -77,7 +79,7 @@ enum class PluginMessageFormat {
|
||||
CodeCompletion,
|
||||
LanguageServerCapabilities,
|
||||
SignatureHelp,
|
||||
DocumentFormatting
|
||||
ProjectSearchResult
|
||||
};
|
||||
|
||||
class PluginIDType {
|
||||
@@ -153,6 +155,10 @@ struct PluginMessage {
|
||||
return *static_cast<const LSPSignatureHelp*>( data );
|
||||
}
|
||||
|
||||
const ProjectSearch::Result& asProjectSearchResult() const {
|
||||
return *static_cast<const ProjectSearch::Result*>( data );
|
||||
}
|
||||
|
||||
const PluginIDType& asPluginID() const { return *static_cast<const PluginIDType*>( data ); }
|
||||
|
||||
bool isResponse() const { return -1 != responseID && 0 != responseID; }
|
||||
|
||||
Reference in New Issue
Block a user