rucoa 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -2
  3. data/Gemfile.lock +3 -3
  4. data/README.md +4 -1
  5. data/data/definitions_ruby_3_1 +6594 -6594
  6. data/lib/rucoa/configuration.rb +22 -12
  7. data/lib/rucoa/definition_store.rb +270 -158
  8. data/lib/rucoa/definitions/method_definition.rb +11 -11
  9. data/lib/rucoa/definitions/module_definition.rb +14 -0
  10. data/lib/rucoa/handler_concerns/configuration_requestable.rb +7 -7
  11. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +11 -11
  12. data/lib/rucoa/handler_concerns/text_document_position_parameters.rb +29 -0
  13. data/lib/rucoa/handler_concerns/text_document_uri_parameters.rb +21 -0
  14. data/lib/rucoa/handler_concerns.rb +2 -0
  15. data/lib/rucoa/handlers/base.rb +9 -9
  16. data/lib/rucoa/handlers/initialize_handler.rb +1 -0
  17. data/lib/rucoa/handlers/initialized_handler.rb +16 -16
  18. data/lib/rucoa/handlers/text_document_code_action_handler.rb +12 -12
  19. data/lib/rucoa/handlers/text_document_completion_handler.rb +85 -99
  20. data/lib/rucoa/handlers/text_document_definition_handler.rb +11 -30
  21. data/lib/rucoa/handlers/text_document_did_close_handler.rb +2 -8
  22. data/lib/rucoa/handlers/text_document_did_open_handler.rb +3 -7
  23. data/lib/rucoa/handlers/text_document_document_highlight_handler.rb +256 -0
  24. data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +47 -76
  25. data/lib/rucoa/handlers/text_document_formatting_handler.rb +15 -23
  26. data/lib/rucoa/handlers/text_document_hover_handler.rb +24 -43
  27. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +17 -25
  28. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +11 -19
  29. data/lib/rucoa/handlers/text_document_signature_help_handler.rb +17 -36
  30. data/lib/rucoa/handlers.rb +1 -0
  31. data/lib/rucoa/node_concerns/body.rb +1 -1
  32. data/lib/rucoa/node_concerns/qualified_name.rb +5 -5
  33. data/lib/rucoa/node_concerns/rescue.rb +21 -0
  34. data/lib/rucoa/node_concerns.rb +1 -0
  35. data/lib/rucoa/node_inspector.rb +17 -6
  36. data/lib/rucoa/nodes/base.rb +48 -48
  37. data/lib/rucoa/nodes/begin_node.rb +2 -0
  38. data/lib/rucoa/nodes/block_node.rb +24 -0
  39. data/lib/rucoa/nodes/case_node.rb +24 -0
  40. data/lib/rucoa/nodes/const_node.rb +26 -26
  41. data/lib/rucoa/nodes/def_node.rb +14 -13
  42. data/lib/rucoa/nodes/ensure_node.rb +19 -0
  43. data/lib/rucoa/nodes/for_node.rb +8 -0
  44. data/lib/rucoa/nodes/if_node.rb +32 -0
  45. data/lib/rucoa/nodes/resbody_node.rb +8 -0
  46. data/lib/rucoa/nodes/rescue_node.rb +17 -0
  47. data/lib/rucoa/nodes/send_node.rb +40 -0
  48. data/lib/rucoa/nodes/until_node.rb +8 -0
  49. data/lib/rucoa/nodes/when_node.rb +8 -0
  50. data/lib/rucoa/nodes/while_node.rb +8 -0
  51. data/lib/rucoa/nodes.rb +10 -1
  52. data/lib/rucoa/parser_builder.rb +16 -2
  53. data/lib/rucoa/range.rb +9 -3
  54. data/lib/rucoa/rbs/class_definition_mapper.rb +1 -0
  55. data/lib/rucoa/rbs/constant_definition_mapper.rb +5 -5
  56. data/lib/rucoa/rbs/method_definition_mapper.rb +18 -18
  57. data/lib/rucoa/rbs/module_definition_mapper.rb +17 -12
  58. data/lib/rucoa/rbs/ruby_definitions_loader.rb +5 -5
  59. data/lib/rucoa/rubocop/configuration_checker.rb +7 -7
  60. data/lib/rucoa/server.rb +25 -24
  61. data/lib/rucoa/source.rb +5 -5
  62. data/lib/rucoa/source_store.rb +8 -8
  63. data/lib/rucoa/version.rb +1 -1
  64. data/lib/rucoa/yard/definition_generators/attribute_reader_definition_generator.rb +17 -1
  65. data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +17 -1
  66. data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +1 -0
  67. data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +14 -1
  68. data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +6 -0
  69. metadata +16 -3
  70. data/lib/rucoa/nodes/defs_node.rb +0 -33
@@ -3,6 +3,8 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentSelectionRangeHandler < Base
6
+ include HandlerConcerns::TextDocumentUriParameters
7
+
6
8
  def call
7
9
  return unless responsible?
8
10
 
@@ -18,17 +20,6 @@ module Rucoa
18
20
 
19
21
  private
20
22
 
21
- # @return [Boolean]
22
- def responsible?
23
- configuration.enables_selection_range? &&
24
- !source.nil?
25
- end
26
-
27
- # @return [Rucoa::Source]
28
- def source
29
- @source ||= source_store.get(uri)
30
- end
31
-
32
23
  # @return [Array<Rucoa::Position>]
33
24
  def positions
34
25
  request.dig('params', 'positions').map do |position|
@@ -36,9 +27,10 @@ module Rucoa
36
27
  end
37
28
  end
38
29
 
39
- # @return [String]
40
- def uri
41
- request.dig('params', 'textDocument', 'uri')
30
+ # @return [Boolean]
31
+ def responsible?
32
+ configuration.enables_selection_range? &&
33
+ !source.nil?
42
34
  end
43
35
 
44
36
  class SelectionRangeProvider
@@ -128,6 +120,11 @@ module Rucoa
128
120
 
129
121
  private
130
122
 
123
+ # @return [Rucoa::Range]
124
+ def expression_range
125
+ Range.from_parser_range(@node.location.expression)
126
+ end
127
+
131
128
  # @return [Rucoa::Range]
132
129
  def inner_range
133
130
  Range.new(
@@ -135,11 +132,6 @@ module Rucoa
135
132
  Position.from_parser_range_beginning(@node.location.end)
136
133
  )
137
134
  end
138
-
139
- # @return [Rucoa::Range]
140
- def expression_range
141
- Range.from_parser_range(@node.location.expression)
142
- end
143
135
  end
144
136
  end
145
137
  end
@@ -3,12 +3,29 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentSignatureHelpHandler < Base
6
+ include HandlerConcerns::TextDocumentPositionParameters
7
+ include HandlerConcerns::TextDocumentUriParameters
8
+
6
9
  def call
7
10
  respond(signature_help)
8
11
  end
9
12
 
10
13
  private
11
14
 
15
+ # @return [Array<Rucoa::Definitions::MethodDefinition>]
16
+ def method_definitions
17
+ NodeInspector.new(
18
+ definition_store: definition_store,
19
+ node: node
20
+ ).method_definitions
21
+ end
22
+
23
+ # @return [Boolean]
24
+ def responsible?
25
+ configuration.enables_signature_help? &&
26
+ node.is_a?(Nodes::SendNode)
27
+ end
28
+
12
29
  # @return [Hash]
13
30
  def signature_help
14
31
  return unless responsible?
@@ -18,12 +35,6 @@ module Rucoa
18
35
  }
19
36
  end
20
37
 
21
- # @return [Boolean]
22
- def responsible?
23
- configuration.enables_signature_help? &&
24
- node.is_a?(Nodes::SendNode)
25
- end
26
-
27
38
  # @return [Array<Hash>]
28
39
  def signature_informations
29
40
  method_definitions.map do |method_definition|
@@ -33,36 +44,6 @@ module Rucoa
33
44
  }
34
45
  end
35
46
  end
36
-
37
- # @return [Array<Rucoa::Definitions::MethodDefinition>]
38
- def method_definitions
39
- NodeInspector.new(
40
- definition_store: definition_store,
41
- node: node
42
- ).method_definitions
43
- end
44
-
45
- # @return [Rucoa::Nodes::Base, nil]
46
- def node
47
- @node ||= source.node_at(position)
48
- end
49
-
50
- # @return [Rucoa::Position]
51
- def position
52
- Position.from_vscode_position(
53
- request.dig('params', 'position')
54
- )
55
- end
56
-
57
- # @return [Rucoa::Source]
58
- def source
59
- source_store.get(uri)
60
- end
61
-
62
- # @return [String]
63
- def uri
64
- request.dig('params', 'textDocument', 'uri')
65
- end
66
47
  end
67
48
  end
68
49
  end
@@ -13,6 +13,7 @@ module Rucoa
13
13
  autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
14
14
  autoload :TextDocumentDidCloseHandler, 'rucoa/handlers/text_document_did_close_handler'
15
15
  autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
16
+ autoload :TextDocumentDocumentHighlightHandler, 'rucoa/handlers/text_document_document_highlight_handler'
16
17
  autoload :TextDocumentDocumentSymbolHandler, 'rucoa/handlers/text_document_document_symbol_handler'
17
18
  autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
18
19
  autoload :TextDocumentHoverHandler, 'rucoa/handlers/text_document_hover_handler'
@@ -5,7 +5,7 @@ module Rucoa
5
5
  module Body
6
6
  # @return [Rucoa::Nodes::BeginNode, nil]
7
7
  def body
8
- children[2]
8
+ children.last
9
9
  end
10
10
 
11
11
  # @return [Array<Rucoa::Nodes::Base>]
@@ -3,6 +3,11 @@
3
3
  module Rucoa
4
4
  module NodeConcerns
5
5
  module QualifiedName
6
+ # @return [String]
7
+ def name
8
+ raise NotImplementedError
9
+ end
10
+
6
11
  # @return [String]
7
12
  def qualified_name
8
13
  [
@@ -10,11 +15,6 @@ module Rucoa
10
15
  *each_ancestor(:class, :constant, :module).map(&:name)
11
16
  ].reverse.join('::')
12
17
  end
13
-
14
- # @return [String]
15
- def name
16
- raise NotImplementedError
17
- end
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module NodeConcerns
5
+ module Rescue
6
+ # @return [Rucoa::Nodes::EnsureNode, nil]
7
+ def ensure
8
+ return unless body.is_a?(Nodes::EnsureNode)
9
+
10
+ body
11
+ end
12
+
13
+ # @return [Rucoa::Nodes::RescueNode, nil]
14
+ def rescue
15
+ return unless body.is_a?(Nodes::RescueNode)
16
+
17
+ body
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,5 +4,6 @@ module Rucoa
4
4
  module NodeConcerns
5
5
  autoload :Body, 'rucoa/node_concerns/body'
6
6
  autoload :QualifiedName, 'rucoa/node_concerns/qualified_name'
7
+ autoload :Rescue, 'rucoa/node_concerns/rescue'
7
8
  end
8
9
  end
@@ -51,7 +51,7 @@ module Rucoa
51
51
  def return_types
52
52
  case @node.type
53
53
  when :const
54
- ["singleton<#{@node.name}>"]
54
+ return_types_for_const
55
55
  when :lvar
56
56
  return_types_for_lvar
57
57
  when :send
@@ -103,16 +103,22 @@ module Rucoa
103
103
  )
104
104
  end
105
105
 
106
- # @return [Boolean]
107
- def singleton_method_call?
108
- @node.is_a?(Nodes::ConstNode)
109
- end
110
-
111
106
  # @return [String, nil]
112
107
  def nearest_def_qualified_name
113
108
  @node.each_ancestor(:def).first&.qualified_name
114
109
  end
115
110
 
111
+ # @return [Array<String>]
112
+ def return_types_for_const
113
+ qualified_name = @definition_store.resolve_constant(
114
+ UnqualifiedName.new(
115
+ chained_name: @node.chained_name,
116
+ module_nesting: @node.module_nesting
117
+ )
118
+ )
119
+ ["singleton<#{qualified_name}>"]
120
+ end
121
+
116
122
  # @return [Array<String>]
117
123
  def return_types_for_lvar
118
124
  qualified_name = nearest_def_qualified_name
@@ -136,5 +142,10 @@ module Rucoa
136
142
  )&.return_types
137
143
  end.compact
138
144
  end
145
+
146
+ # @return [Boolean]
147
+ def singleton_method_call?
148
+ @node.is_a?(Nodes::ConstNode)
149
+ end
139
150
  end
140
151
  end
@@ -14,16 +14,6 @@ module Rucoa
14
14
  end
15
15
  end
16
16
 
17
- # @return [Rucoa::Nodes::Base, nil]
18
- def parent
19
- @mutable_attributes[:parent]
20
- end
21
-
22
- # @param node [Rucoa::Nodes::Base]
23
- def parent=(node)
24
- @mutable_attributes[:parent] = node
25
- end
26
-
27
17
  # @return [Array<Rucoa::Nodes::Base>]
28
18
  def ancestors
29
19
  each_ancestor.to_a
@@ -73,23 +63,6 @@ module Rucoa
73
63
  self
74
64
  end
75
65
 
76
- # @note Override.
77
- # Some nodes change their type depending on the context.
78
- # For example, `const` node can be `casgn` node.
79
- # @return [Rucoa::Nodes::Base]
80
- def updated(
81
- type = nil,
82
- children = nil,
83
- properties = {}
84
- )
85
- properties[:location] ||= @location
86
- ParserBuilder.node_class_for(type || @type).new(
87
- type || @type,
88
- children || @children,
89
- properties
90
- )
91
- end
92
-
93
66
  # @param position [Rucoa::Position]
94
67
  # @return [Boolean]
95
68
  def include_position?(position)
@@ -98,6 +71,29 @@ module Rucoa
98
71
  Range.from_parser_range(location.expression).include?(position)
99
72
  end
100
73
 
74
+ # @return [Array<String>]
75
+ # @example return ["Bar::Foo", "Foo"] for class Foo::Bar::Baz
76
+ # node = Rucoa::Source.new(
77
+ # content: <<~RUBY,
78
+ # module Foo
79
+ # module Bar
80
+ # module Baz
81
+ # end
82
+ # end
83
+ # end
84
+ # RUBY
85
+ # uri: 'file:///path/to/foo/bar/baz.rb'
86
+ # ).node_at(
87
+ # Rucoa::Position.new(
88
+ # column: 4,
89
+ # line: 3
90
+ # )
91
+ # )
92
+ # expect(node.module_nesting).to eq(['Foo::Bar', 'Foo'])
93
+ def module_nesting
94
+ each_ancestor(:class, :module).map(&:qualified_name)
95
+ end
96
+
101
97
  # @note namespace is a String representation of `Module.nesting`.
102
98
  # @return [String]
103
99
  # @example returns namespace
@@ -130,27 +126,31 @@ module Rucoa
130
126
  module_nesting.first || 'Object'
131
127
  end
132
128
 
133
- # @return [Array<String>]
134
- # @example return ["Bar::Foo", "Foo"] for class Foo::Bar::Baz
135
- # node = Rucoa::Source.new(
136
- # content: <<~RUBY,
137
- # module Foo
138
- # module Bar
139
- # module Baz
140
- # end
141
- # end
142
- # end
143
- # RUBY
144
- # uri: 'file:///path/to/foo/bar/baz.rb'
145
- # ).node_at(
146
- # Rucoa::Position.new(
147
- # column: 4,
148
- # line: 3
149
- # )
150
- # )
151
- # expect(node.module_nesting).to eq(['Foo::Bar', 'Foo'])
152
- def module_nesting
153
- each_ancestor(:class, :module).map(&:qualified_name)
129
+ # @return [Rucoa::Nodes::Base, nil]
130
+ def parent
131
+ @mutable_attributes[:parent]
132
+ end
133
+
134
+ # @param node [Rucoa::Nodes::Base]
135
+ def parent=(node)
136
+ @mutable_attributes[:parent] = node
137
+ end
138
+
139
+ # @note Override.
140
+ # Some nodes change their type depending on the context.
141
+ # For example, `const` node can be `casgn` node.
142
+ # @return [Rucoa::Nodes::Base]
143
+ def updated(
144
+ type = nil,
145
+ children = nil,
146
+ properties = {}
147
+ )
148
+ properties[:location] ||= @location
149
+ ParserBuilder.node_class_for(type || @type).new(
150
+ type || @type,
151
+ children || @children,
152
+ properties
153
+ )
154
154
  end
155
155
 
156
156
  protected
@@ -3,6 +3,8 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  class BeginNode < Base
6
+ include NodeConcerns::Body
7
+ include NodeConcerns::Rescue
6
8
  end
7
9
  end
8
10
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class BlockNode < Base
6
+ include NodeConcerns::Body
7
+ include NodeConcerns::Rescue
8
+
9
+ # @return [Rucoa::Nodes::SendNode]
10
+ # @example returns send node
11
+ # node = Rucoa::Source.new(
12
+ # content: <<~RUBY,
13
+ # foo do
14
+ # end
15
+ # RUBY
16
+ # uri: 'file:///foo.rb'
17
+ # ).root_node
18
+ # expect(node.send_node.name).to eq('foo')
19
+ def send_node
20
+ children[0]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class CaseNode < Base
6
+ # @return [Array<Rucoa::Nodes::Base>]
7
+ # @example returns when nodes
8
+ # node = Rucoa::Source.new(
9
+ # content: <<~RUBY,
10
+ # case foo
11
+ # when 1
12
+ # when 2
13
+ # else
14
+ # end
15
+ # RUBY
16
+ # uri: 'file:///foo.rb'
17
+ # ).root_node
18
+ # expect(node.whens.length).to eq(2)
19
+ def whens
20
+ children[1...-1]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -3,32 +3,6 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  class ConstNode < Base
6
- # @return [String]
7
- # @example returns "A" for "A"
8
- # node = Rucoa::Source.new(
9
- # content: <<~RUBY,
10
- # A
11
- # RUBY
12
- # uri: 'file:///path/to/a.rb'
13
- # ).root_node
14
- # expect(node.name).to eq('A')
15
- # @example returns "B" for "A::B"
16
- # node = Rucoa::Source.new(
17
- # content: <<~RUBY,
18
- # A::B
19
- # RUBY
20
- # uri: 'file:///path/to/a.rb'
21
- # ).node_at(
22
- # Rucoa::Position.new(
23
- # column: 4,
24
- # line: 1
25
- # )
26
- # )
27
- # expect(node.name).to eq('B')
28
- def name
29
- children[1].to_s
30
- end
31
-
32
6
  # @return [String]
33
7
  # @example returns "A" for "A"
34
8
  # node = Rucoa::Source.new(
@@ -91,6 +65,32 @@ module Rucoa
91
65
  each_ancestor(:class, :module).map(&:qualified_name)
92
66
  end
93
67
 
68
+ # @return [String]
69
+ # @example returns "A" for "A"
70
+ # node = Rucoa::Source.new(
71
+ # content: <<~RUBY,
72
+ # A
73
+ # RUBY
74
+ # uri: 'file:///path/to/a.rb'
75
+ # ).root_node
76
+ # expect(node.name).to eq('A')
77
+ # @example returns "B" for "A::B"
78
+ # node = Rucoa::Source.new(
79
+ # content: <<~RUBY,
80
+ # A::B
81
+ # RUBY
82
+ # uri: 'file:///path/to/a.rb'
83
+ # ).node_at(
84
+ # Rucoa::Position.new(
85
+ # column: 4,
86
+ # line: 1
87
+ # )
88
+ # )
89
+ # expect(node.name).to eq('B')
90
+ def name
91
+ children[1].to_s
92
+ end
93
+
94
94
  private
95
95
 
96
96
  # @return [Rucoa::Nodes::Base, nil]
@@ -3,6 +3,18 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  class DefNode < Base
6
+ include NodeConcerns::Body
7
+ include NodeConcerns::Rescue
8
+
9
+ # @return [String]
10
+ def method_marker
11
+ if singleton?
12
+ '.'
13
+ else
14
+ '#'
15
+ end
16
+ end
17
+
6
18
  # @return [String]
7
19
  # @example returns method name
8
20
  # node = Rucoa::Source.new(
@@ -23,7 +35,7 @@ module Rucoa
23
35
  # )
24
36
  # expect(node.name).to eq('baz')
25
37
  def name
26
- children[0].to_s
38
+ children[-3].to_s
27
39
  end
28
40
 
29
41
  # @return [String]
@@ -55,18 +67,7 @@ module Rucoa
55
67
 
56
68
  # @return [Boolean]
57
69
  def singleton?
58
- each_ancestor(:sclass).any?
59
- end
60
-
61
- private
62
-
63
- # @return [String]
64
- def method_marker
65
- if singleton?
66
- '.'
67
- else
68
- '#'
69
- end
70
+ type == :defs || each_ancestor(:sclass).any?
70
71
  end
71
72
  end
72
73
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class EnsureNode < Base
6
+ # @return [Rucoa::Nodes::Base, nil]
7
+ def body
8
+ children[0]
9
+ end
10
+
11
+ # @return [Rucoa::Nodes::RescueNode, nil]
12
+ def rescue
13
+ return unless body.is_a?(Nodes::RescueNode)
14
+
15
+ body
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ForNode < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class IfNode < Base
6
+ # @return [Rucoa::Nodes::Base, nil]
7
+ def branch_else
8
+ children[2]
9
+ end
10
+
11
+ # @return [Rucoa::Nodes::Base, nil]
12
+ def branch_if
13
+ children[1]
14
+ end
15
+
16
+ # @return [Rucoa::Nodes::Base]
17
+ def condition
18
+ children[0]
19
+ end
20
+
21
+ # @return [Rucoa::Nodes::IfNode, nil]
22
+ def elsif
23
+ branch_else if branch_else.is_a?(Nodes::IfNode)
24
+ end
25
+
26
+ # @return [Boolean]
27
+ def elsif?
28
+ parent.is_a?(Nodes::IfNode) && eql?(parent.elsif)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ResbodyNode < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class RescueNode < Base
6
+ # @return [Rucoa::Nodes::Base, nil]
7
+ def body
8
+ children[0]
9
+ end
10
+
11
+ # @return [Array<Rucoa::Nodes::Resbody>]
12
+ def resbodies
13
+ children[1..-2]
14
+ end
15
+ end
16
+ end
17
+ end