Skip to content

Remove old inlay hints code #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ It is built with only standard library dependencies. It additionally ships with
- [BasicVisitor](#basicvisitor)
- [Language server](#language-server)
- [textDocument/formatting](#textdocumentformatting)
- [textDocument/inlayHints](#textdocumentinlayhints)
- [textDocument/inlayHint](#textdocumentinlayhint)
- [syntaxTree/visualizing](#syntaxtreevisualizing)
- [Plugins](#plugins)
- [Configuration](#configuration)
Expand Down Expand Up @@ -402,15 +402,15 @@ By default, the language server is relatively minimal, mostly meant to provide a

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.

### textDocument/inlayHints
### textDocument/inlayHint

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:

```ruby
1 + 2 * 3
```

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:
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:

```ruby
1 + ₍2 * 3₎
Expand Down
26 changes: 6 additions & 20 deletions lib/syntax_tree/language_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,7 @@ def run
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], true))
write(id: id, result: inlay_hints(store[uri]))
in {
method: "syntaxTree/visualizing",
id:,
Expand Down Expand Up @@ -119,21 +112,14 @@ def format(source)
}
end

def inlay_hints(source, proprietary)
inlay_hints = InlayHints.find(SyntaxTree.parse(source))
serialize = ->(position, text) { { position: position, text: text } }

if proprietary
{
before: inlay_hints.before.map(&serialize),
after: inlay_hints.after.map(&serialize)
}
else
inlay_hints.all
end
def inlay_hints(source)
visitor = InlayHints.new
SyntaxTree.parse(source).accept(visitor)
visitor.hints
rescue Parser::ParseError
# If there is a parse error, then we're not going to return any inlay
# hints for this source.
[]
end

def write(value)
Expand Down
76 changes: 39 additions & 37 deletions lib/syntax_tree/language_server/inlay_hints.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,37 @@

module SyntaxTree
class LanguageServer
# 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:
# This class provides inlay hints for the language server. For more
# information, see the spec here:
# https://github.com/microsoft/language-server-protocol/issues/956.
#
class InlayHints < Visitor
attr_reader :stack, :all, :before, :after
# This represents a hint that is going to be displayed in the editor.
class Hint
attr_reader :line, :character, :label

def initialize(line:, character:, label:)
@line = line
@character = character
@label = label
end

# This is the shape that the LSP expects.
def to_json(*opts)
{
position: {
line: line,
character: character
},
label: label
}.to_json(*opts)
end
end

attr_reader :stack, :hints

def initialize
@stack = []
@all = []
@before = Hash.new { |hash, key| hash[key] = +"" }
@after = Hash.new { |hash, key| hash[key] = +"" }
@hints = []
end

def visit(node)
Expand Down Expand Up @@ -98,14 +114,11 @@ 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
},
hints << Hint.new(
line: node.location.start_line - 1,
character: node.location.start_column + "rescue".length,
label: " StandardError"
}
)
end

super
Expand All @@ -128,31 +141,20 @@ def visit_unary(node)
super
end

def self.find(program)
visitor = new
visitor.visit(program)
visitor
end

private

def parentheses(location)
all << {
position: {
line: location.start_line - 1,
character: location.start_column
},
hints << Hint.new(
line: location.start_line - 1,
character: location.start_column,
label: "₍"
}
all << {
position: {
line: location.end_line - 1,
character: location.end_column
},
)

hints << Hint.new(
line: location.end_line - 1,
character: location.end_column,
label: "₎"
}
before[location.start_char] << "₍"
after[location.end_char] << "₎"
)
end
end
end
Expand Down
12 changes: 6 additions & 6 deletions lib/syntax_tree/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1641,12 +1641,12 @@ def on_heredoc_end(value)
heredoc = @heredocs[-1]

location =
Location.token(
line: lineno,
char: char_pos,
column: current_column,
size: value.size + 1
)
Location.token(
line: lineno,
char: char_pos,
column: current_column,
size: value.size + 1
)

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

Expand Down
42 changes: 11 additions & 31 deletions test/language_server/inlay_hints_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,36 @@ module SyntaxTree
class LanguageServer
class InlayHintsTest < Minitest::Test
def test_assignments_in_parameters
hints = find("def foo(a = b = c); end")

assert_equal(1, hints.before.length)
assert_equal(1, hints.after.length)
assert_equal(2, hints.all.length)
assert_hints(2, "def foo(a = b = c); end")
end

def test_operators_in_binaries
hints = find("1 + 2 * 3")

assert_equal(1, hints.before.length)
assert_equal(1, hints.after.length)
assert_equal(2, hints.all.length)
assert_hints(2, "1 + 2 * 3")
end

def test_binaries_in_assignments
hints = find("a = 1 + 2")

assert_equal(1, hints.before.length)
assert_equal(1, hints.after.length)
assert_equal(2, hints.all.length)
assert_hints(2, "a = 1 + 2")
end

def test_nested_ternaries
hints = find("a ? b : c ? d : e")

assert_equal(1, hints.before.length)
assert_equal(1, hints.after.length)
assert_equal(2, hints.all.length)
assert_hints(2, "a ? b : c ? d : e")
end

def test_bare_rescue
hints = find("begin; rescue; end")

assert_equal(1, hints.after.length)
assert_equal(1, hints.all.length)
assert_hints(1, "begin; rescue; end")
end

def test_unary_in_binary
hints = find("-a + b")

assert_equal(1, hints.before.length)
assert_equal(1, hints.after.length)
assert_equal(2, hints.all.length)
assert_hints(2, "-a + b")
end

private

def find(source)
InlayHints.find(SyntaxTree.parse(source))
def assert_hints(expected, source)
visitor = InlayHints.new
SyntaxTree.parse(source).accept(visitor)

assert_equal(expected, visitor.hints.length)
end
end
end
Expand Down
13 changes: 6 additions & 7 deletions test/language_server_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ def to_hash
end
end

class TextDocumentInlayHints < Struct.new(:id, :uri)
class TextDocumentInlayHint < Struct.new(:id, :uri)
def to_hash
{
method: "textDocument/inlayHints",
method: "textDocument/inlayHint",
id: id,
params: {
textDocument: {
Expand Down Expand Up @@ -120,7 +120,7 @@ def test_formatting
end
end

def test_inlay_hints
def test_inlay_hint
messages = [
Initialize.new(1),
TextDocumentDidOpen.new("file:///path/to/file.rb", <<~RUBY),
Expand All @@ -129,18 +129,17 @@ def test_inlay_hints
rescue
end
RUBY
TextDocumentInlayHints.new(2, "file:///path/to/file.rb"),
TextDocumentInlayHint.new(2, "file:///path/to/file.rb"),
Shutdown.new(3)
]

case run_server(messages)
in [
{ id: 1, result: { capabilities: Hash } },
{ id: 2, result: { before:, after: } },
{ id: 2, result: hints },
{ id: 3, result: {} }
]
assert_equal(1, before.length)
assert_equal(2, after.length)
assert_equal(3, hints.length)
end
end

Expand Down