Skip to content

Commit c9ce212

Browse files
authored
Merge pull request #108 from ruby-syntax-tree/remove-old-inlay-hints
Remove old inlay hints code
2 parents 201d27d + 5ee15c7 commit c9ce212

File tree

6 files changed

+71
-104
lines changed

6 files changed

+71
-104
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ It is built with only standard library dependencies. It additionally ships with
3535
- [BasicVisitor](#basicvisitor)
3636
- [Language server](#language-server)
3737
- [textDocument/formatting](#textdocumentformatting)
38-
- [textDocument/inlayHints](#textdocumentinlayhints)
38+
- [textDocument/inlayHint](#textdocumentinlayhint)
3939
- [syntaxTree/visualizing](#syntaxtreevisualizing)
4040
- [Plugins](#plugins)
4141
- [Configuration](#configuration)
@@ -402,15 +402,15 @@ By default, the language server is relatively minimal, mostly meant to provide a
402402

403403
As mentioned above, the language server responds to formatting requests with the formatted document. It typically responds on the order of tens of milliseconds, so it should be fast enough for any IDE.
404404

405-
### textDocument/inlayHints
405+
### textDocument/inlayHint
406406

407407
The language server also responds to the relatively new inlay hints request. This request allows the language server to define additional information that should exist in the source code as helpful hints to the developer. In our case we use it to display things like implicit parentheses. For example, if you had the following code:
408408

409409
```ruby
410410
1 + 2 * 3
411411
```
412412

413-
Implicity, the `2 * 3` is going to be executed first because the `*` operator has higher precedence than the `+` operator. However, to ease mental overhead, our language server includes small parentheses to make this explicit, as in:
413+
Implicity, the `2 * 3` is going to be executed first because the `*` operator has higher precedence than the `+` operator. To ease mental overhead, our language server includes small parentheses to make this explicit, as in:
414414

415415
```ruby
416416
1 +2 * 3

lib/syntax_tree/language_server.rb

+6-20
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,7 @@ def run
6666
id:,
6767
params: { textDocument: { uri: } }
6868
}
69-
write(id: id, result: inlay_hints(store[uri], false))
70-
in {
71-
# proprietary RPC (deprecated) between this gem and vscode-syntax-tree
72-
method: "textDocument/inlayHints",
73-
id:,
74-
params: { textDocument: { uri: } }
75-
}
76-
write(id: id, result: inlay_hints(store[uri], true))
69+
write(id: id, result: inlay_hints(store[uri]))
7770
in {
7871
method: "syntaxTree/visualizing",
7972
id:,
@@ -119,21 +112,14 @@ def format(source)
119112
}
120113
end
121114

122-
def inlay_hints(source, proprietary)
123-
inlay_hints = InlayHints.find(SyntaxTree.parse(source))
124-
serialize = ->(position, text) { { position: position, text: text } }
125-
126-
if proprietary
127-
{
128-
before: inlay_hints.before.map(&serialize),
129-
after: inlay_hints.after.map(&serialize)
130-
}
131-
else
132-
inlay_hints.all
133-
end
115+
def inlay_hints(source)
116+
visitor = InlayHints.new
117+
SyntaxTree.parse(source).accept(visitor)
118+
visitor.hints
134119
rescue Parser::ParseError
135120
# If there is a parse error, then we're not going to return any inlay
136121
# hints for this source.
122+
[]
137123
end
138124

139125
def write(value)

lib/syntax_tree/language_server/inlay_hints.rb

+39-37
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,37 @@
22

33
module SyntaxTree
44
class LanguageServer
5-
# This class provides inlay hints for the language server. It existed
6-
# before the spec was finalized so, so it provides two result formats:
7-
# aligned with the spec (`#all`) and proprietary (`#before` and `#after`).
8-
#
9-
# For more information, see the spec here:
5+
# This class provides inlay hints for the language server. For more
6+
# information, see the spec here:
107
# https://github.com/microsoft/language-server-protocol/issues/956.
11-
#
128
class InlayHints < Visitor
13-
attr_reader :stack, :all, :before, :after
9+
# This represents a hint that is going to be displayed in the editor.
10+
class Hint
11+
attr_reader :line, :character, :label
12+
13+
def initialize(line:, character:, label:)
14+
@line = line
15+
@character = character
16+
@label = label
17+
end
18+
19+
# This is the shape that the LSP expects.
20+
def to_json(*opts)
21+
{
22+
position: {
23+
line: line,
24+
character: character
25+
},
26+
label: label
27+
}.to_json(*opts)
28+
end
29+
end
30+
31+
attr_reader :stack, :hints
1432

1533
def initialize
1634
@stack = []
17-
@all = []
18-
@before = Hash.new { |hash, key| hash[key] = +"" }
19-
@after = Hash.new { |hash, key| hash[key] = +"" }
35+
@hints = []
2036
end
2137

2238
def visit(node)
@@ -98,14 +114,11 @@ def visit_if_op(node)
98114
#
99115
def visit_rescue(node)
100116
if node.exception.nil?
101-
after[node.location.start_char + "rescue".length] << " StandardError"
102-
all << {
103-
position: {
104-
line: node.location.start_line - 1,
105-
character: node.location.start_column + "rescue".length
106-
},
117+
hints << Hint.new(
118+
line: node.location.start_line - 1,
119+
character: node.location.start_column + "rescue".length,
107120
label: " StandardError"
108-
}
121+
)
109122
end
110123

111124
super
@@ -128,31 +141,20 @@ def visit_unary(node)
128141
super
129142
end
130143

131-
def self.find(program)
132-
visitor = new
133-
visitor.visit(program)
134-
visitor
135-
end
136-
137144
private
138145

139146
def parentheses(location)
140-
all << {
141-
position: {
142-
line: location.start_line - 1,
143-
character: location.start_column
144-
},
147+
hints << Hint.new(
148+
line: location.start_line - 1,
149+
character: location.start_column,
145150
label: "₍"
146-
}
147-
all << {
148-
position: {
149-
line: location.end_line - 1,
150-
character: location.end_column
151-
},
151+
)
152+
153+
hints << Hint.new(
154+
line: location.end_line - 1,
155+
character: location.end_column,
152156
label: "₎"
153-
}
154-
before[location.start_char] << "₍"
155-
after[location.end_char] << "₎"
157+
)
156158
end
157159
end
158160
end

lib/syntax_tree/parser.rb

+6-6
Original file line numberDiff line numberDiff line change
@@ -1641,12 +1641,12 @@ def on_heredoc_end(value)
16411641
heredoc = @heredocs[-1]
16421642

16431643
location =
1644-
Location.token(
1645-
line: lineno,
1646-
char: char_pos,
1647-
column: current_column,
1648-
size: value.size + 1
1649-
)
1644+
Location.token(
1645+
line: lineno,
1646+
char: char_pos,
1647+
column: current_column,
1648+
size: value.size + 1
1649+
)
16501650

16511651
heredoc_end = HeredocEnd.new(value: value.chomp, location: location)
16521652

test/language_server/inlay_hints_test.rb

+11-31
Original file line numberDiff line numberDiff line change
@@ -7,56 +7,36 @@ module SyntaxTree
77
class LanguageServer
88
class InlayHintsTest < Minitest::Test
99
def test_assignments_in_parameters
10-
hints = find("def foo(a = b = c); end")
11-
12-
assert_equal(1, hints.before.length)
13-
assert_equal(1, hints.after.length)
14-
assert_equal(2, hints.all.length)
10+
assert_hints(2, "def foo(a = b = c); end")
1511
end
1612

1713
def test_operators_in_binaries
18-
hints = find("1 + 2 * 3")
19-
20-
assert_equal(1, hints.before.length)
21-
assert_equal(1, hints.after.length)
22-
assert_equal(2, hints.all.length)
14+
assert_hints(2, "1 + 2 * 3")
2315
end
2416

2517
def test_binaries_in_assignments
26-
hints = find("a = 1 + 2")
27-
28-
assert_equal(1, hints.before.length)
29-
assert_equal(1, hints.after.length)
30-
assert_equal(2, hints.all.length)
18+
assert_hints(2, "a = 1 + 2")
3119
end
3220

3321
def test_nested_ternaries
34-
hints = find("a ? b : c ? d : e")
35-
36-
assert_equal(1, hints.before.length)
37-
assert_equal(1, hints.after.length)
38-
assert_equal(2, hints.all.length)
22+
assert_hints(2, "a ? b : c ? d : e")
3923
end
4024

4125
def test_bare_rescue
42-
hints = find("begin; rescue; end")
43-
44-
assert_equal(1, hints.after.length)
45-
assert_equal(1, hints.all.length)
26+
assert_hints(1, "begin; rescue; end")
4627
end
4728

4829
def test_unary_in_binary
49-
hints = find("-a + b")
50-
51-
assert_equal(1, hints.before.length)
52-
assert_equal(1, hints.after.length)
53-
assert_equal(2, hints.all.length)
30+
assert_hints(2, "-a + b")
5431
end
5532

5633
private
5734

58-
def find(source)
59-
InlayHints.find(SyntaxTree.parse(source))
35+
def assert_hints(expected, source)
36+
visitor = InlayHints.new
37+
SyntaxTree.parse(source).accept(visitor)
38+
39+
assert_equal(expected, visitor.hints.length)
6040
end
6141
end
6242
end

test/language_server_test.rb

+6-7
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ def to_hash
7272
end
7373
end
7474

75-
class TextDocumentInlayHints < Struct.new(:id, :uri)
75+
class TextDocumentInlayHint < Struct.new(:id, :uri)
7676
def to_hash
7777
{
78-
method: "textDocument/inlayHints",
78+
method: "textDocument/inlayHint",
7979
id: id,
8080
params: {
8181
textDocument: {
@@ -120,7 +120,7 @@ def test_formatting
120120
end
121121
end
122122

123-
def test_inlay_hints
123+
def test_inlay_hint
124124
messages = [
125125
Initialize.new(1),
126126
TextDocumentDidOpen.new("file:///path/to/file.rb", <<~RUBY),
@@ -129,18 +129,17 @@ def test_inlay_hints
129129
rescue
130130
end
131131
RUBY
132-
TextDocumentInlayHints.new(2, "file:///path/to/file.rb"),
132+
TextDocumentInlayHint.new(2, "file:///path/to/file.rb"),
133133
Shutdown.new(3)
134134
]
135135

136136
case run_server(messages)
137137
in [
138138
{ id: 1, result: { capabilities: Hash } },
139-
{ id: 2, result: { before:, after: } },
139+
{ id: 2, result: hints },
140140
{ id: 3, result: {} }
141141
]
142-
assert_equal(1, before.length)
143-
assert_equal(2, after.length)
142+
assert_equal(3, hints.length)
144143
end
145144
end
146145

0 commit comments

Comments
 (0)