Class: LspRouter
- Inherits:
-
Object
- Object
- LspRouter
- Defined in:
- lib/lsp_router.rb,
lib/lsp_router/cli.rb,
lib/lsp_router/config.rb,
lib/lsp_router/version.rb,
lib/lsp_router/client_side.rb,
lib/lsp_router/server_side.rb,
lib/lsp_router/capability_request.rb
Overview
LspRouter
Defined Under Namespace
Classes: CLI, ClientSide, Config, ServerSide
Constant Summary collapse
- VERSION =
'0.2.1'- CAPABILITY_REQUEST =
{ textDocumentSync: [ 'textDocument/willSaveWaitUntil', ], notebookDocumentSync: [ # Notification only ], completionProvider: [ 'textDocument/completion', 'completionItem/resolve', ], hoverProvider: [ 'textDocument/hover', ], signatureHelpProvider: [ 'textDocument/signatureHelp', ], declarationProvider: [ 'textDocument/declaration', ], definitionProvider: [ 'textDocument/definition', ], typeDefinitionProvider: [ 'textDocument/typeDefinition', ], implementationProvider: [ 'textDocument/implementation', ], referencesProvider: [ 'textDocument/references', ], documentHighlightProvider: [ 'textDocument/documentHighlight', ], documentSymbolProvider: [ 'textDocument/documentSymbol', ], codeActionProvider: [ 'textDocument/codeAction', 'codeAction/resolve', ], codeLensProvider: [ 'textDocument/codeLens', 'codeLens/resolve', 'workspace/codeLens/refresh', ], documentLinkProvider: [ 'textDocument/documentLink', 'documentLink/resolve', ], colorProvider: [ 'textDocument/documentColor', 'textDocument/colorPresentation', ], documentFormattingProvider: [ 'textDocument/formatting', ], documentRangeFormattingProvider: [ 'textDocument/rangeFormatting', ], documentOnTypeFormattingProvider: [ 'textDocument/onTypeFormatting', ], renameProvider: [ 'textDocument/rename', 'textDocument/prepareRename', ], foldingRangeProvider: [ 'textDocument/foldingRange', ], executeCommandProvider: [ 'textDocument/selectionRange', 'workspace/executeCommand', ], selectionRangeProvider: [ ], linkedEditingRangeProvider: [ 'textDocument/linkedEditingRange', ], callHierarchyProvider: [ 'textDocument/prepareCallHierarchy', 'callHierarchy/incomingCalls', 'callHierarchy/outgoingCalls', ], semanticTokensProvider: [ 'textDocument/semanticTokens', 'textDocument/semanticTokens/full', 'textDocument/semanticTokens/full/delta', 'textDocument/semanticTokens/range', 'workspace/semanticTokens/refresh', ], monikerProvider: [ 'textDocument/moniker', ], typeHierarchyProvider: [ 'textDocument/prepareTypeHierarchy', 'typeHierarchy/supertypes', 'typeHierarchy/subtypes', ], inlineValueProvider: [ 'textDocument/inlineValue', 'workspace/inlineValue/refresh', ], inlayHintProvider: [ 'textDocument/inlayHint', 'inlayHint/resolve', 'workspace/inlayHint/refresh', ], diagnosticProvider: [ 'textDocument/diagnostic', 'workspace/diagnostic', 'workspace/diagnostic/refresh', ], workspaceSymbolProvider: [ 'workspace/symbol', 'workspaceSymbol/resolve', ], workspace: { workspaceFolders: [ 'workspace/workspaceFolders', ], fileOperations: [ 'workspace/willCreateFiles', 'workspace/willRenameFiles', 'workspace/willDeleteFiles', ], }, }
Instance Method Summary collapse
- #client_loop ⇒ Object
- #initial_packet ⇒ Object
-
#initialize(config, port: nil, logfile: nil) ⇒ LspRouter
constructor
A new instance of LspRouter.
- #loop ⇒ Object
- #run ⇒ Object
- #server_loop ⇒ Object
Constructor Details
#initialize(config, port: nil, logfile: nil) ⇒ LspRouter
Returns a new instance of LspRouter.
16 17 18 19 20 21 22 23 24 25 |
# File 'lib/lsp_router.rb', line 16 def initialize(config, port: nil, logfile: nil) @config = config @port = port logfile ||= config.logfile || $stderr @logger = Logger.new(logfile, level: Logger.const_get(config.loglevel.upcase)) @logger.info "LspRouter: start" @config.servers.each do |server| @logger.info "server: #{server.info}" end end |
Instance Method Details
#client_loop ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/lsp_router.rb', line 77 def client_loop Thread.new do Thread.abort_on_exception = true while true data = @client.read break unless data if data['method'] == 'shutdown' || data['method'] == 'exit' @servers.each{_1.write(data)} break if data['method'] == 'exit' next end if data['id'] # request or response if data['method'] # request server = @req_server[data['method']] || @primary else # response server_name, id = JSON.parse(data['id']) data['id'] = id server = @server_map[server_name] end server.write(data) else # notification @servers.each{_1.write(data)} end end @logger.info "client: end" end end |
#initial_packet ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/lsp_router.rb', line 57 def initial_packet req = @client.read req['params']['capabilities']['general'] ||= {} req['params']['capabilities']['general']['positionEncodings'] = [@config.encoding] res = nil @servers.each do |server| data = server.init(req) if res res['result']['capabilities'].update(data.dig('result', 'capabilities')){|_, v, _| v} else res = data end server.requests.each do |req| @req_server[req] ||= server end end @logger.debug "req_server: #{@req_server.transform_values(&:name).inspect}" @client.write(res) end |
#loop ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/lsp_router.rb', line 45 def loop @servers = @config.servers.map{LspRouter::ServerSide.new(_1, logger: @logger)} @primary = @servers.first @server_map = @servers.map.to_h{[_1.name.to_s, _1]} @req_server = {} initial_packet threads = server_loop threads.push client_loop threads.each(&:join) end |
#run ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/lsp_router.rb', line 27 def run if @port @logger.info "mode: port:#{@port}" Socket.tcp_server_loop(@port) do |sock, _| @client = LspRouter::ClientSide.new(sock, sock, logger: @logger) loop end else @logger.info "mode: stdio" @client = LspRouter::ClientSide.new($stdin, $stdout, logger: @logger) loop end rescue => e @logger.error e ensure @logger.info "LspRouter: stop" end |
#server_loop ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/lsp_router.rb', line 105 def server_loop @servers.map do |server| Thread.new do Thread.abort_on_exception = true while true data = server.read break unless data if data['id'] && data['method'] # request data['id'] = [server.name, data['id']].to_json end @client.write(data) end @logger.info "server: [#{server.name}] end" end end end |