-
Notifications
You must be signed in to change notification settings - Fork 183
/
Copy pathshow_syntax_tree.rb
76 lines (64 loc) · 2.1 KB
/
show_syntax_tree.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# typed: strict
# frozen_string_literal: true
module RubyLsp
module Requests
# 
#
# Show syntax tree is a custom [LSP
# request](https://microsoft.github.io/language-server-protocol/specification#requestMessage) that displays the AST
# for the current document or for the current selection in a new tab.
#
# # Example
#
# ```ruby
# # Executing the Ruby LSP: Show syntax tree command will display the AST for the document
# 1 + 1
# # (program (statements ((binary (int "1") + (int "1")))))
# ```
#
class ShowSyntaxTree < Request
extend T::Sig
sig { params(document: RubyDocument, range: T.nilable(T::Hash[Symbol, T.untyped])).void }
def initialize(document, range)
super()
@document = document
@range = range
@tree = T.let(document.parse_result.value, Prism::ProgramNode)
end
sig { override.returns(String) }
def perform
return ast_for_range if @range
output_string = +""
PP.pp(@tree, output_string)
output_string
end
private
sig { returns(String) }
def ast_for_range
range = T.must(@range)
scanner = @document.create_scanner
start_char = scanner.find_char_position(range[:start])
end_char = scanner.find_char_position(range[:end])
queue = @tree.statements.body.dup
found_nodes = []
until queue.empty?
node = queue.shift
next unless node
loc = node.location
# If the node is fully covered by the selection, then we found one of the nodes to be displayed and don't want
# to continue descending into its children
if (start_char..end_char).cover?(loc.start_offset..loc.end_offset)
found_nodes << node
else
T.unsafe(queue).unshift(*node.child_nodes)
end
end
found_nodes.map do |node|
output_string = +""
PP.pp(node, output_string)
output_string
end.join("\n")
end
end
end
end