Class: Spoom::LSP::Client
- Inherits:
-
Object
- Object
- Spoom::LSP::Client
- Defined in:
- lib/spoom/sorbet/lsp.rb
Instance Method Summary collapse
-
#close ⇒ Object
: -> void.
-
#definitions(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Array.
-
#document_symbols(uri) ⇒ Object
: (String uri) -> Array.
-
#hover(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Hover?.
-
#initialize(sorbet_bin, *sorbet_args, path: ".") ⇒ Client
constructor
: (String sorbet_bin, *String sorbet_args, ?path: String) -> void.
-
#next_id ⇒ Object
: -> Integer.
-
#open(workspace_path) ⇒ Object
: (String workspace_path) -> void.
-
#read ⇒ Object
: -> Hash[untyped, untyped]?.
-
#read_raw ⇒ Object
: -> String?.
-
#references(uri, line, column, include_decl = true) ⇒ Object
: (String uri, Integer line, Integer column, ?bool include_decl) -> Array.
-
#send(message) ⇒ Object
: (Message message) -> Hash[untyped, untyped]?.
-
#send_raw(json_string) ⇒ Object
: (String json_string) -> void.
-
#signatures(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Array.
-
#symbols(query) ⇒ Object
: (String query) -> Array.
-
#type_definitions(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Array.
Constructor Details
#initialize(sorbet_bin, *sorbet_args, path: ".") ⇒ Client
: (String sorbet_bin, *String sorbet_args, ?path: String) -> void
15 16 17 18 19 20 21 22 |
# File 'lib/spoom/sorbet/lsp.rb', line 15 def initialize(sorbet_bin, *sorbet_args, path: ".") @id = T.let(0, Integer) @open = T.let(false, T::Boolean) io_in, io_out, io_err, _status = T.unsafe(Open3).popen3(sorbet_bin, *sorbet_args, chdir: path) @in = T.let(io_in, IO) @out = T.let(io_out, IO) @err = T.let(io_err, IO) end |
Instance Method Details
#close ⇒ Object
: -> void
227 228 229 230 231 232 233 |
# File 'lib/spoom/sorbet/lsp.rb', line 227 def close send(Request.new(next_id, "shutdown", {})) @in.close @out.close @err.close @open = false end |
#definitions(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Array
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/spoom/sorbet/lsp.rb', line 129 def definitions(uri, line, column) json = send(Request.new( next_id, "textDocument/definition", { "textDocument" => { "uri" => uri, }, "position" => { "line" => line, "character" => column, }, }, )) return [] unless json && json["result"] json["result"].map { |loc| Location.from_json(loc) } end |
#document_symbols(uri) ⇒ Object
: (String uri) -> Array
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/spoom/sorbet/lsp.rb', line 210 def document_symbols(uri) json = send(Request.new( next_id, "textDocument/documentSymbol", { "textDocument" => { "uri" => uri, }, }, )) return [] unless json && json["result"] json["result"].map { |loc| DocumentSymbol.from_json(loc) } end |
#hover(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Hover?
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/spoom/sorbet/lsp.rb', line 87 def hover(uri, line, column) json = send(Request.new( next_id, "textDocument/hover", { "textDocument" => { "uri" => uri, }, "position" => { "line" => line, "character" => column, }, }, )) return unless json && json["result"] Hover.from_json(json["result"]) end |
#next_id ⇒ Object
: -> Integer
25 26 27 |
# File 'lib/spoom/sorbet/lsp.rb', line 25 def next_id @id += 1 end |
#open(workspace_path) ⇒ Object
: (String workspace_path) -> void
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/spoom/sorbet/lsp.rb', line 70 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
: -> Hash[untyped, untyped]?
52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/spoom/sorbet/lsp.rb', line 52 def read raw_string = read_raw return unless raw_string json = JSON.parse(raw_string) # 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
: -> String?
41 42 43 44 45 46 47 48 49 |
# File 'lib/spoom/sorbet/lsp.rb', line 41 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
: (String uri, Integer line, Integer column, ?bool include_decl) -> Array
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/spoom/sorbet/lsp.rb', line 171 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, }, }, )) return [] unless json && json["result"] json["result"].map { |loc| Location.from_json(loc) } end |
#send(message) ⇒ Object
: (Message message) -> Hash[untyped, untyped]?
35 36 37 38 |
# File 'lib/spoom/sorbet/lsp.rb', line 35 def send() send_raw(.to_json) read if .is_a?(Request) end |
#send_raw(json_string) ⇒ Object
: (String json_string) -> void
30 31 32 |
# File 'lib/spoom/sorbet/lsp.rb', line 30 def send_raw(json_string) @in.puts("Content-Length:#{json_string.length}\r\n\r\n#{json_string}") end |
#signatures(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Array
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/spoom/sorbet/lsp.rb', line 108 def signatures(uri, line, column) json = send(Request.new( next_id, "textDocument/signatureHelp", { "textDocument" => { "uri" => uri, }, "position" => { "line" => line, "character" => column, }, }, )) return [] unless json && json["result"] && json["result"]["signatures"] json["result"]["signatures"].map { |loc| SignatureHelp.from_json(loc) } end |
#symbols(query) ⇒ Object
: (String query) -> Array
195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/spoom/sorbet/lsp.rb', line 195 def symbols(query) json = send(Request.new( next_id, "workspace/symbol", { "query" => query, }, )) return [] unless json && json["result"] json["result"].map { |loc| DocumentSymbol.from_json(loc) } end |
#type_definitions(uri, line, column) ⇒ Object
: (String uri, Integer line, Integer column) -> Array
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/spoom/sorbet/lsp.rb', line 150 def type_definitions(uri, line, column) json = send(Request.new( next_id, "textDocument/typeDefinition", { "textDocument" => { "uri" => uri, }, "position" => { "line" => line, "character" => column, }, }, )) return [] unless json && json["result"] json["result"].map { |loc| Location.from_json(loc) } end |