diff --git a/lib/syntax_tree/language_server.rb b/lib/syntax_tree/language_server.rb index 31c91f9c..1f06b48e 100644 --- a/lib/syntax_tree/language_server.rb +++ b/lib/syntax_tree/language_server.rb @@ -61,11 +61,19 @@ def run } write(id: id, result: [format(store[uri])]) in { + # official RPC in LSP spec 3.17 + method: "textDocument/inlayHint", + id:, + params: { textDocument: { uri: } } + } + write(id: id, result: inlay_hints(store[uri], false)) + in { + # proprietary RPC (deprecated) between this gem and vscode-syntax-tree method: "textDocument/inlayHints", id:, params: { textDocument: { uri: } } } - write(id: id, result: inlay_hints(store[uri])) + write(id: id, result: inlay_hints(store[uri], true)) in { method: "syntaxTree/visualizing", id:, @@ -85,6 +93,9 @@ def run def capabilities { documentFormattingProvider: true, + inlayHintProvider: { + resolveProvider: false + }, textDocumentSync: { change: 1, openClose: true @@ -108,14 +119,18 @@ def format(source) } end - def inlay_hints(source) + def inlay_hints(source, proprietary) inlay_hints = InlayHints.find(SyntaxTree.parse(source)) serialize = ->(position, text) { { position: position, text: text } } - { - before: inlay_hints.before.map(&serialize), - after: inlay_hints.after.map(&serialize) - } + if proprietary + { + before: inlay_hints.before.map(&serialize), + after: inlay_hints.after.map(&serialize) + } + else + inlay_hints.all + end rescue Parser::ParseError # If there is a parse error, then we're not going to return any inlay # hints for this source. diff --git a/lib/syntax_tree/language_server/inlay_hints.rb b/lib/syntax_tree/language_server/inlay_hints.rb index 089355a7..4be8a765 100644 --- a/lib/syntax_tree/language_server/inlay_hints.rb +++ b/lib/syntax_tree/language_server/inlay_hints.rb @@ -2,18 +2,19 @@ module SyntaxTree class LanguageServer - # This class provides inlay hints for the language server. It is loosely - # designed around the LSP spec, but existed before the spec was finalized so - # is a little different for now. + # This class provides inlay hints for the language server. It existed + # before the spec was finalized so, so it provides two result formats: + # aligned with the spec (`#all`) and proprietary (`#before` and `#after`). # # For more information, see the spec here: # https://github.com/microsoft/language-server-protocol/issues/956. # class InlayHints < Visitor - attr_reader :stack, :before, :after + attr_reader :stack, :all, :before, :after def initialize @stack = [] + @all = [] @before = Hash.new { |hash, key| hash[key] = +"" } @after = Hash.new { |hash, key| hash[key] = +"" } end @@ -98,6 +99,13 @@ def visit_if_op(node) def visit_rescue(node) if node.exception.nil? after[node.location.start_char + "rescue".length] << " StandardError" + all << { + position: { + line: node.location.start_line - 1, + character: node.location.start_column + "rescue".length + }, + label: " StandardError" + } end super @@ -129,6 +137,20 @@ def self.find(program) private def parentheses(location) + all << { + position: { + line: location.start_line - 1, + character: location.start_column + }, + label: "₍" + } + all << { + position: { + line: location.end_line - 1, + character: location.end_column + }, + label: "₎" + } before[location.start_char] << "₍" after[location.end_char] << "₎" end diff --git a/test/language_server/inlay_hints_test.rb b/test/language_server/inlay_hints_test.rb index f652f6d8..35db365a 100644 --- a/test/language_server/inlay_hints_test.rb +++ b/test/language_server/inlay_hints_test.rb @@ -11,6 +11,7 @@ def test_assignments_in_parameters assert_equal(1, hints.before.length) assert_equal(1, hints.after.length) + assert_equal(2, hints.all.length) end def test_operators_in_binaries @@ -18,6 +19,7 @@ def test_operators_in_binaries assert_equal(1, hints.before.length) assert_equal(1, hints.after.length) + assert_equal(2, hints.all.length) end def test_binaries_in_assignments @@ -25,6 +27,7 @@ def test_binaries_in_assignments assert_equal(1, hints.before.length) assert_equal(1, hints.after.length) + assert_equal(2, hints.all.length) end def test_nested_ternaries @@ -32,12 +35,14 @@ def test_nested_ternaries assert_equal(1, hints.before.length) assert_equal(1, hints.after.length) + assert_equal(2, hints.all.length) end def test_bare_rescue hints = find("begin; rescue; end") assert_equal(1, hints.after.length) + assert_equal(1, hints.all.length) end def test_unary_in_binary @@ -45,6 +50,7 @@ def test_unary_in_binary assert_equal(1, hints.before.length) assert_equal(1, hints.after.length) + assert_equal(2, hints.all.length) end private