Class: Spoom::LSP::Client
- Inherits:
-
Object
- Object
- Spoom::LSP::Client
- Defined in:
- lib/spoom/sorbet/lsp.rb
Instance Method Summary collapse
- #close ⇒ Object
- #definitions(uri, line, column) ⇒ Object
- #document_symbols(uri) ⇒ Object
- #hover(uri, line, column) ⇒ Object
-
#initialize(sorbet_cmd, *sorbet_args, path: ".") ⇒ Client
constructor
A new instance of Client.
- #next_id ⇒ Object
-
#open(workspace_path) ⇒ Object
LSP requests.
- #read ⇒ Object
- #read_raw ⇒ Object
- #references(uri, line, column, include_decl = true) ⇒ Object
- #send(message) ⇒ Object
- #send_raw(json_string) ⇒ Object
- #signatures(uri, line, column) ⇒ Object
- #symbols(query) ⇒ Object
- #type_definitions(uri, line, column) ⇒ Object
Constructor Details
#initialize(sorbet_cmd, *sorbet_args, path: ".") ⇒ Client
Returns a new instance of Client.
14 15 16 17 18 19 20 21 |
# File 'lib/spoom/sorbet/lsp.rb', line 14 def initialize(sorbet_cmd, *sorbet_args, path: ".") @id = 0 Bundler.with_clean_env do opts = {} opts[:chdir] = path @in, @out, @err, @status = Open3.popen3([sorbet_cmd, *sorbet_args].join(" "), opts) end end |
Instance Method Details
#close ⇒ Object
188 189 190 191 192 193 |
# File 'lib/spoom/sorbet/lsp.rb', line 188 def close send(Request.new(next_id, "shutdown", nil)) @in.close @out.close @err.close end |
#definitions(uri, line, column) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/spoom/sorbet/lsp.rb', line 110 def definitions(uri, line, column) json = send(Request.new( next_id, 'textDocument/definition', { 'textDocument' => { 'uri' => uri, }, 'position' => { 'line' => line, 'character' => column, }, } )) json['result'].map { |loc| Location.from_json(loc) } end |
#document_symbols(uri) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/spoom/sorbet/lsp.rb', line 175 def document_symbols(uri) json = send(Request.new( next_id, 'textDocument/documentSymbol', { 'textDocument' => { 'uri' => uri, }, } )) json['result'].map { |loc| DocumentSymbol.from_json(loc) } end |
#hover(uri, line, column) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/spoom/sorbet/lsp.rb', line 75 def hover(uri, line, column) json = send(Request.new( next_id, 'textDocument/hover', { 'textDocument' => { 'uri' => uri, }, 'position' => { 'line' => line, 'character' => column, }, } )) return nil unless json['result'] Hover.from_json(json['result']) end |
#next_id ⇒ Object
23 24 25 |
# File 'lib/spoom/sorbet/lsp.rb', line 23 def next_id @id += 1 end |
#open(workspace_path) ⇒ Object
LSP requests
60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/spoom/sorbet/lsp.rb', line 60 def open(workspace_path) raise Error::AlreadyOpen, "Error: CLI already opened" if @open send(Request.new( next_id, 'initialize', { 'rootPath' => workspace_path, 'rootUri' => "file://#{workspace_path}", 'capabilities' => {}, }, )) send(Notification.new('initialized', {})) @open = true end |
#read ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/spoom/sorbet/lsp.rb', line 46 def read json = JSON.parse(read_raw) # Handle error in the LSP protocol raise ResponseError.from_json(json['error']) if json['error'] # Handle typechecking errors raise Error::Diagnostics.from_json(json['params']) if json['method'] == "textDocument/publishDiagnostics" json end |
#read_raw ⇒ Object
36 37 38 39 40 41 42 43 44 |
# File 'lib/spoom/sorbet/lsp.rb', line 36 def read_raw header = @out.gets # Sorbet returned an error and forgot to answer raise Error::BadHeaders, "bad response headers" unless header&.match?(/Content-Length: /) len = header.slice(::Range.new(16, nil)).to_i @out.read(len + 2) # +2 'cause of the final \r\n end |
#references(uri, line, column, include_decl = true) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/spoom/sorbet/lsp.rb', line 144 def references(uri, line, column, include_decl = true) json = send(Request.new( next_id, 'textDocument/references', { 'textDocument' => { 'uri' => uri, }, 'position' => { 'line' => line, 'character' => column, }, 'context' => { 'includeDeclaration' => include_decl, }, } )) json['result'].map { |loc| Location.from_json(loc) } end |
#send(message) ⇒ Object
31 32 33 34 |
# File 'lib/spoom/sorbet/lsp.rb', line 31 def send() send_raw(.to_json) read if .is_a?(Request) end |
#send_raw(json_string) ⇒ Object
27 28 29 |
# File 'lib/spoom/sorbet/lsp.rb', line 27 def send_raw(json_string) @in.puts("Content-Length:#{json_string.length}\r\n\r\n#{json_string}") end |
#signatures(uri, line, column) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/spoom/sorbet/lsp.rb', line 93 def signatures(uri, line, column) json = send(Request.new( next_id, 'textDocument/signatureHelp', { 'textDocument' => { 'uri' => uri, }, 'position' => { 'line' => line, 'character' => column, }, } )) json['result']['signatures'].map { |loc| SignatureHelp.from_json(loc) } end |
#symbols(query) ⇒ Object
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/spoom/sorbet/lsp.rb', line 164 def symbols(query) json = send(Request.new( next_id, 'workspace/symbol', { 'query' => query, } )) json['result'].map { |loc| DocumentSymbol.from_json(loc) } end |
#type_definitions(uri, line, column) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/spoom/sorbet/lsp.rb', line 127 def type_definitions(uri, line, column) json = send(Request.new( next_id, 'textDocument/typeDefinition', { 'textDocument' => { 'uri' => uri, }, 'position' => { 'line' => line, 'character' => column, }, } )) json['result'].map { |loc| Location.from_json(loc) } end |