rbs 1.6.0 → 1.7.0.beta.2

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +0 -4
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +26 -0
  5. data/Gemfile +1 -0
  6. data/Rakefile +7 -22
  7. data/core/enumerator.rbs +1 -0
  8. data/core/io.rbs +1 -1
  9. data/core/kernel.rbs +4 -4
  10. data/core/trace_point.rbs +1 -1
  11. data/ext/rbs_extension/constants.c +140 -0
  12. data/ext/rbs_extension/constants.h +72 -0
  13. data/ext/rbs_extension/extconf.rb +3 -0
  14. data/ext/rbs_extension/lexer.c +1070 -0
  15. data/ext/rbs_extension/lexer.h +145 -0
  16. data/ext/rbs_extension/location.c +295 -0
  17. data/ext/rbs_extension/location.h +59 -0
  18. data/ext/rbs_extension/main.c +9 -0
  19. data/ext/rbs_extension/parser.c +2422 -0
  20. data/ext/rbs_extension/parser.h +23 -0
  21. data/ext/rbs_extension/parserstate.c +313 -0
  22. data/ext/rbs_extension/parserstate.h +141 -0
  23. data/ext/rbs_extension/rbs_extension.h +40 -0
  24. data/ext/rbs_extension/ruby_objs.c +585 -0
  25. data/ext/rbs_extension/ruby_objs.h +46 -0
  26. data/ext/rbs_extension/unescape.c +65 -0
  27. data/goodcheck.yml +1 -1
  28. data/lib/rbs/ast/comment.rb +0 -12
  29. data/lib/rbs/buffer.rb +4 -0
  30. data/lib/rbs/cli.rb +5 -8
  31. data/lib/rbs/collection/sources/git.rb +18 -3
  32. data/lib/rbs/errors.rb +22 -1
  33. data/lib/rbs/location.rb +221 -217
  34. data/lib/rbs/location_aux.rb +121 -0
  35. data/lib/rbs/locator.rb +10 -7
  36. data/lib/rbs/parser_aux.rb +31 -0
  37. data/lib/rbs/types.rb +2 -3
  38. data/lib/rbs/version.rb +1 -1
  39. data/lib/rbs/writer.rb +4 -2
  40. data/lib/rbs.rb +3 -7
  41. data/rbs.gemspec +2 -1
  42. data/sig/ancestor_builder.rbs +2 -2
  43. data/sig/annotation.rbs +2 -2
  44. data/sig/comment.rbs +7 -7
  45. data/sig/constant_table.rbs +1 -1
  46. data/sig/declarations.rbs +9 -9
  47. data/sig/definition.rbs +1 -1
  48. data/sig/definition_builder.rbs +2 -2
  49. data/sig/errors.rbs +40 -25
  50. data/sig/location.rbs +46 -78
  51. data/sig/locator.rbs +2 -2
  52. data/sig/members.rbs +7 -7
  53. data/sig/method_types.rbs +3 -3
  54. data/sig/parser.rbs +13 -20
  55. data/sig/types.rbs +45 -27
  56. data/sig/writer.rbs +1 -1
  57. data/stdlib/json/0/json.rbs +3 -3
  58. metadata +25 -7
  59. data/lib/rbs/parser.rb +0 -3614
@@ -0,0 +1,46 @@
1
+ #ifndef RBS__RUBY_OBJS_H
2
+ #define RBS__RUBY_OBJS_H
3
+
4
+ #include "ruby.h"
5
+
6
+ VALUE rbs_alias(VALUE typename, VALUE location);
7
+ VALUE rbs_ast_annotation(VALUE string, VALUE location);
8
+ VALUE rbs_ast_comment(VALUE string, VALUE location);
9
+ VALUE rbs_ast_decl_alias(VALUE name, VALUE type, VALUE annotations, VALUE location, VALUE comment);
10
+ VALUE rbs_ast_decl_class_super(VALUE name, VALUE args, VALUE location);
11
+ VALUE rbs_ast_decl_class(VALUE name, VALUE type_params, VALUE super_class, VALUE members, VALUE annotations, VALUE location, VALUE comment);
12
+ VALUE rbs_ast_decl_constant(VALUE name, VALUE type, VALUE location, VALUE comment);
13
+ VALUE rbs_ast_decl_global(VALUE name, VALUE type, VALUE location, VALUE comment);
14
+ VALUE rbs_ast_decl_interface(VALUE name, VALUE type_params, VALUE members, VALUE annotations, VALUE location, VALUE comment);
15
+ VALUE rbs_ast_decl_module_self(VALUE name, VALUE args, VALUE location);
16
+ VALUE rbs_ast_decl_module_type_params_param(VALUE name, VALUE variance, VALUE skip_validation, VALUE location);
17
+ VALUE rbs_ast_decl_module_type_params();
18
+ VALUE rbs_ast_decl_module(VALUE name, VALUE type_params, VALUE self_types, VALUE members, VALUE annotations, VALUE location, VALUE comment);
19
+ VALUE rbs_ast_members_alias(VALUE new_name, VALUE old_name, VALUE kind, VALUE annotations, VALUE location, VALUE comment);
20
+ VALUE rbs_ast_members_attribute(VALUE klass, VALUE name, VALUE type, VALUE ivar_name, VALUE kind, VALUE annotations, VALUE location, VALUE comment);
21
+ VALUE rbs_ast_members_method_definition(VALUE name, VALUE kind, VALUE types, VALUE annotations, VALUE location, VALUE comment, VALUE overload);
22
+ VALUE rbs_ast_members_mixin(VALUE klass, VALUE name, VALUE args, VALUE annotations, VALUE location, VALUE comment);
23
+ VALUE rbs_ast_members_variable(VALUE klass, VALUE name, VALUE type, VALUE location, VALUE comment);
24
+ VALUE rbs_ast_members_visibility(VALUE klass, VALUE location);
25
+ VALUE rbs_base_type(VALUE klass, VALUE location);
26
+ VALUE rbs_block(VALUE type, VALUE required);
27
+ VALUE rbs_class_instance(VALUE typename, VALUE type_args, VALUE location);
28
+ VALUE rbs_class_singleton(VALUE typename, VALUE location);
29
+ VALUE rbs_function_param(VALUE type, VALUE name, VALUE location);
30
+ VALUE rbs_function(VALUE required_positional_params, VALUE optional_positional_params, VALUE rest_positional_params, VALUE trailing_positional_params, VALUE required_keywords, VALUE optional_keywords, VALUE rest_keywords, VALUE return_type);
31
+ VALUE rbs_interface(VALUE typename, VALUE type_args, VALUE location);
32
+ VALUE rbs_intersection(VALUE types, VALUE location);
33
+ VALUE rbs_literal(VALUE literal, VALUE location);
34
+ VALUE rbs_method_type(VALUE type_params, VALUE type, VALUE block, VALUE location);
35
+ VALUE rbs_namespace(VALUE path, VALUE absolute);
36
+ VALUE rbs_optional(VALUE type, VALUE location);
37
+ VALUE rbs_proc(VALUE function, VALUE block, VALUE location);
38
+ VALUE rbs_record(VALUE fields, VALUE location);
39
+ VALUE rbs_tuple(VALUE types, VALUE location);
40
+ VALUE rbs_type_name(VALUE namespace, VALUE name);
41
+ VALUE rbs_union(VALUE types, VALUE location);
42
+ VALUE rbs_variable(VALUE name, VALUE location);
43
+
44
+ void pp(VALUE object);
45
+
46
+ #endif
@@ -0,0 +1,65 @@
1
+ #include "rbs_extension.h"
2
+
3
+ static VALUE REGEXP = 0;
4
+ static VALUE HASH = 0;
5
+
6
+ static const char *regexp_str = "\\\\[abefnrstv\"]";
7
+
8
+ static ID gsub = 0;
9
+
10
+ void rbs_unescape_string(VALUE string) {
11
+ if (!REGEXP) {
12
+ REGEXP = rb_reg_new(regexp_str, strlen(regexp_str), 0);
13
+ rb_global_variable(&REGEXP);
14
+ }
15
+
16
+ if (!gsub) {
17
+ gsub = rb_intern("gsub!");
18
+ }
19
+
20
+ if (!HASH) {
21
+ HASH = rb_hash_new();
22
+ rb_hash_aset(HASH, rb_str_new_literal("\\a"), rb_str_new_literal("\a"));
23
+ rb_hash_aset(HASH, rb_str_new_literal("\\b"), rb_str_new_literal("\b"));
24
+ rb_hash_aset(HASH, rb_str_new_literal("\\e"), rb_str_new_literal("\e"));
25
+ rb_hash_aset(HASH, rb_str_new_literal("\\f"), rb_str_new_literal("\f"));
26
+ rb_hash_aset(HASH, rb_str_new_literal("\\n"), rb_str_new_literal("\n"));
27
+ rb_hash_aset(HASH, rb_str_new_literal("\\r"), rb_str_new_literal("\r"));
28
+ rb_hash_aset(HASH, rb_str_new_literal("\\s"), rb_str_new_literal(" "));
29
+ rb_hash_aset(HASH, rb_str_new_literal("\\t"), rb_str_new_literal("\t"));
30
+ rb_hash_aset(HASH, rb_str_new_literal("\\v"), rb_str_new_literal("\v"));
31
+ rb_hash_aset(HASH, rb_str_new_literal("\\\""), rb_str_new_literal("\""));
32
+ rb_global_variable(&HASH);
33
+ }
34
+
35
+ rb_funcall(string, gsub, 2, REGEXP, HASH);
36
+ }
37
+
38
+ VALUE rbs_unquote_string(parserstate *state, range rg, int offset_bytes) {
39
+ VALUE string = state->lexstate->string;
40
+ rb_encoding *enc = rb_enc_get(string);
41
+
42
+ unsigned int first_char = rb_enc_mbc_to_codepoint(
43
+ RSTRING_PTR(string) + rg.start.byte_pos + offset_bytes,
44
+ RSTRING_END(string),
45
+ enc
46
+ );
47
+
48
+ int byte_length = rg.end.byte_pos - rg.start.byte_pos - offset_bytes;
49
+
50
+ if (first_char == '"' || first_char == '\'' || first_char == '`') {
51
+ int bs = rb_enc_codelen(first_char, enc);
52
+ offset_bytes += bs;
53
+ byte_length -= 2 * bs;
54
+ }
55
+
56
+ char *buffer = RSTRING_PTR(state->lexstate->string) + rg.start.byte_pos + offset_bytes;
57
+ VALUE str = rb_enc_str_new(buffer, byte_length, enc);
58
+
59
+ if (first_char == '\"') {
60
+ rbs_unescape_string(str);
61
+ }
62
+
63
+ return str;
64
+ }
65
+
data/goodcheck.yml CHANGED
@@ -40,7 +40,7 @@ rules:
40
40
  glob:
41
41
  - "**/*.rbs"
42
42
  justification:
43
- - When you strictly want `true | false`.
43
+ - When you strictly want `true | false`. Use `bool` in this case.
44
44
  pass:
45
45
  - "(arg: boolish)"
46
46
  - "{ () -> boolish }"
@@ -22,18 +22,6 @@ module RBS
22
22
  def to_json(state = _ = nil)
23
23
  { string: string, location: location }.to_json(state)
24
24
  end
25
-
26
- def concat(string:, location:)
27
- @string.concat string
28
-
29
- if loc = @location
30
- loc.concat location
31
- else
32
- @location = location
33
- end
34
-
35
- self
36
- end
37
25
  end
38
26
  end
39
27
  end
data/lib/rbs/buffer.rb CHANGED
@@ -46,5 +46,9 @@ module RBS
46
46
  def last_position
47
47
  content.size
48
48
  end
49
+
50
+ def inspect
51
+ "#<RBS::Buffer:#{__id__} @name=#{name}, @content=#{content.bytesize} bytes, @lines=#{lines.size} lines,>"
52
+ end
49
53
  end
50
54
  end
data/lib/rbs/cli.rb CHANGED
@@ -749,14 +749,11 @@ Examples:
749
749
  args.each do |path|
750
750
  path = Pathname(path)
751
751
  loader.each_file(path, skip_hidden: false, immediate: true) do |file_path|
752
- Parser.parse_signature(file_path.read)
753
- rescue RBS::Parser::SyntaxError => ex
754
- loc = ex.error_value.location
755
- stdout.puts "#{file_path}:#{loc.start_line}:#{loc.start_column}: parse error on value: (#{ex.token_str})"
756
- syntax_error = true
757
- rescue RBS::Parser::SemanticsError => ex
758
- loc = ex.location
759
- stdout.puts "#{file_path}:#{loc.start_line}:#{loc.start_column}: #{ex.original_message}"
752
+ RBS.logger.info "Parsing #{file_path}..."
753
+ buffer = Buffer.new(content: file_path.read, name: file_path)
754
+ Parser.parse_signature(buffer)
755
+ rescue RBS::ParsingError => ex
756
+ stdout.puts ex.message
760
757
  syntax_error = true
761
758
  end
762
759
  end
@@ -1,5 +1,6 @@
1
1
  require 'digest/sha2'
2
2
  require 'open3'
3
+ require 'find'
3
4
 
4
5
  module RBS
5
6
  module Collection
@@ -52,12 +53,26 @@ module RBS
52
53
  private def _install(dest:, config_entry:)
53
54
  gem_name = config_entry['name']
54
55
  version = config_entry['version'] or raise
55
- dest = dest.join(gem_name)
56
+ dest = dest.join(gem_name, version)
56
57
  dest.mkpath
57
58
  src = gem_repo_dir.join(gem_name, version)
58
59
 
59
- FileUtils.cp_r(src, dest)
60
- dest.join(version, METADATA_FILENAME).write(YAML.dump(config_entry))
60
+ cp_r(src, dest)
61
+ dest.join(METADATA_FILENAME).write(YAML.dump(config_entry))
62
+ end
63
+
64
+ private def cp_r(src, dest)
65
+ Find.find(src) do |file_src|
66
+ file_src = Pathname(file_src)
67
+
68
+ # Skip file if it starts with _, such as _test/
69
+ Find.prune if file_src.basename.to_s.start_with?('_')
70
+
71
+ file_src_relative = file_src.relative_path_from(src)
72
+ file_dest = dest.join(file_src_relative)
73
+ file_dest.dirname.mkpath
74
+ FileUtils.copy_entry(file_src, file_dest, false, true) unless file_src.directory?
75
+ end
61
76
  end
62
77
 
63
78
  def to_lockfile
data/lib/rbs/errors.rb CHANGED
@@ -15,10 +15,31 @@ module RBS
15
15
  end
16
16
 
17
17
  class ErrorBase < StandardError; end
18
- class ParsingError < ErrorBase; end
19
18
  class LoadingError < ErrorBase; end
20
19
  class DefinitionError < ErrorBase; end
21
20
 
21
+ class ParsingError < ErrorBase
22
+ attr_reader :location
23
+ attr_reader :error_message
24
+ attr_reader :token_type
25
+
26
+ def initialize(location, error_message, token_type)
27
+ @location = location
28
+ @error_message = error_message
29
+ @token_type = token_type
30
+
31
+ super "#{Location.to_string location}: Syntax error: #{error_message}, token=`#{location.source}` (#{token_type})"
32
+ end
33
+
34
+ def error_value
35
+ location.source
36
+ end
37
+
38
+ def token_str
39
+ token_type
40
+ end
41
+ end
42
+
22
43
  class InvalidTypeApplicationError < DefinitionError
23
44
  attr_reader :type_name
24
45
  attr_reader :args
data/lib/rbs/location.rb CHANGED
@@ -1,217 +1,221 @@
1
- module RBS
2
- class Location
3
- attr_reader :buffer
4
- attr_reader :start_pos
5
- attr_reader :end_pos
6
-
7
- def initialize(buffer:, start_pos:, end_pos:)
8
- @buffer = buffer
9
- @start_pos = start_pos
10
- @end_pos = end_pos
11
- end
12
-
13
- def inspect
14
- "#<#{self.class}:#{self.__id__} @buffer=#{buffer.name}, @pos=#{start_pos}...#{end_pos}, source='#{source.lines.first}', start_line=#{start_line}, start_column=#{start_column}>"
15
- end
16
-
17
- def name
18
- buffer.name
19
- end
20
-
21
- def start_line
22
- start_loc[0]
23
- end
24
-
25
- def start_column
26
- start_loc[1]
27
- end
28
-
29
- def end_line
30
- end_loc[0]
31
- end
32
-
33
- def end_column
34
- end_loc[1]
35
- end
36
-
37
- def start_loc
38
- @start_loc ||= buffer.pos_to_loc(start_pos)
39
- end
40
-
41
- def end_loc
42
- @end_loc ||= buffer.pos_to_loc(end_pos)
43
- end
44
-
45
- def range
46
- start_pos...end_pos
47
- end
48
-
49
- def source
50
- @source ||= buffer.content[start_pos...end_pos] or raise
51
- end
52
-
53
- def to_s
54
- "#{name || "-"}:#{start_line}:#{start_column}...#{end_line}:#{end_column}"
55
- end
56
-
57
- def self.to_string(location, default: "*:*:*...*:*")
58
- location&.to_s || default
59
- end
60
-
61
- def ==(other)
62
- other.is_a?(Location) &&
63
- other.buffer == buffer &&
64
- other.start_pos == start_pos &&
65
- other.end_pos == end_pos
66
- end
67
-
68
- def +(other)
69
- if other
70
- raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
71
-
72
- self.class.new(buffer: buffer,
73
- start_pos: start_pos,
74
- end_pos: other.end_pos)
75
- else
76
- self
77
- end
78
- end
79
-
80
- def concat(*others)
81
- others.each { |other| self << other }
82
- self
83
- end
84
-
85
- def <<(other)
86
- if other
87
- raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
88
- @end_pos = other.end_pos
89
- @source = nil
90
- @end_loc = nil
91
- end
92
- self
93
- end
94
-
95
- def pred?(loc)
96
- loc.is_a?(Location) &&
97
- loc.name == name &&
98
- loc.start_pos == end_pos
99
- end
100
-
101
- def to_json(state = _ = nil)
102
- {
103
- start: {
104
- line: start_line,
105
- column: start_column
106
- },
107
- end: {
108
- line: end_line,
109
- column: end_column
110
- },
111
- buffer: {
112
- name: name&.to_s
113
- }
114
- }.to_json(state)
115
- end
116
-
117
- def with_children(required: {}, optional: {})
118
- # @type var required: Hash[Symbol, Range[Integer] | Location]
119
- # @type var optional: Hash[Symbol, Range[Integer] | Location | nil]
120
-
121
- this = WithChildren.new(buffer: buffer, start_pos: start_pos, end_pos: end_pos)
122
-
123
- req = required.transform_values do |value|
124
- case value
125
- when Location
126
- value.range
127
- else
128
- value
129
- end
130
- end
131
-
132
- opt = optional.transform_values do |value|
133
- case value
134
- when Location
135
- value.range
136
- else
137
- value
138
- end
139
- end
140
-
141
- this.required_children.merge!(req)
142
- this.optional_children.merge!(opt)
143
-
144
- this
145
- end
146
-
147
- class WithChildren < Location
148
- attr_reader :required_children, :optional_children
149
-
150
- def initialize(buffer:, start_pos:, end_pos:)
151
- super(buffer: buffer, start_pos: start_pos, end_pos: end_pos)
152
-
153
- @optional_children = {}
154
- @required_children = {}
155
- end
156
-
157
- def initialize_copy(from)
158
- required_children.merge!(from.required_children)
159
- optional_children.merge!(from.optional_children)
160
- self
161
- end
162
-
163
- def [](key)
164
- case
165
- when required_children.key?(_ = key)
166
- range = required_children[_ = key]
167
- Location.new(buffer: buffer, start_pos: range.begin, end_pos: range.end)
168
- when optional_children.key?(_ = key)
169
- range = required_children[_ = key] || optional_children[_ = key]
170
- if range
171
- Location.new(buffer: buffer, start_pos: range.begin, end_pos: range.end)
172
- end
173
- else
174
- raise "Unknown key given: `#{key}`"
175
- end
176
- end
177
-
178
- def merge_required(hash)
179
- this = dup
180
-
181
- h = hash.transform_values do |value|
182
- case value
183
- when Range
184
- value
185
- when Location
186
- value.range
187
- else
188
- raise
189
- end
190
- end
191
-
192
- this.required_children.merge!(h)
193
-
194
- this
195
- end
196
-
197
- def merge_optional(hash)
198
- this = dup
199
-
200
- h = hash.transform_values do |value|
201
- case value
202
- when Range
203
- value
204
- when Location
205
- value.range
206
- else
207
- nil
208
- end
209
- end
210
-
211
- this.optional_children.merge!(h)
212
-
213
- this
214
- end
215
- end
216
- end
217
- end
1
+ # module RBS
2
+ # class Location
3
+ # attr_reader :buffer
4
+ # attr_reader :start_pos
5
+ # attr_reader :end_pos
6
+
7
+ # def initialize(buffer, start_pos, end_pos)
8
+ # @buffer = buffer
9
+ # @start_pos = start_pos
10
+ # @end_pos = end_pos
11
+ # end
12
+
13
+ # # def self.new(buffer_ = nil, start_pos_ = nil, end_pos_ = nil)
14
+ # # __skip__ = super(buffer_, start_pos_, end_pos_)
15
+ # # end
16
+
17
+ # # def inspect
18
+ # # "#<#{self.class}:#{self.__id__} @buffer=#{buffer.name}, @pos=#{start_pos}...#{end_pos}, source='#{source.lines.first}', start_line=#{start_line}, start_column=#{start_column}>"
19
+ # # end
20
+
21
+ # def name
22
+ # buffer.name
23
+ # end
24
+
25
+ # def start_line
26
+ # start_loc[0]
27
+ # end
28
+
29
+ # def start_column
30
+ # start_loc[1]
31
+ # end
32
+
33
+ # def end_line
34
+ # end_loc[0]
35
+ # end
36
+
37
+ # def end_column
38
+ # end_loc[1]
39
+ # end
40
+
41
+ # def start_loc
42
+ # @start_loc ||= buffer.pos_to_loc(start_pos)
43
+ # end
44
+
45
+ # def end_loc
46
+ # @end_loc ||= buffer.pos_to_loc(end_pos)
47
+ # end
48
+
49
+ # def range
50
+ # start_pos...end_pos
51
+ # end
52
+
53
+ # def source
54
+ # @source ||= buffer.content[start_pos...end_pos] or raise
55
+ # end
56
+
57
+ # def to_s
58
+ # "#{name || "-"}:#{start_line}:#{start_column}...#{end_line}:#{end_column}"
59
+ # end
60
+
61
+ # def self.to_string(location, default: "*:*:*...*:*")
62
+ # location&.to_s || default
63
+ # end
64
+
65
+ # def ==(other)
66
+ # other.is_a?(Location) &&
67
+ # other.buffer == buffer &&
68
+ # other.start_pos == start_pos &&
69
+ # other.end_pos == end_pos
70
+ # end
71
+
72
+ # def +(other)
73
+ # if other
74
+ # raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
75
+
76
+ # self.class.new(buffer: buffer,
77
+ # start_pos: start_pos,
78
+ # end_pos: other.end_pos)
79
+ # else
80
+ # self
81
+ # end
82
+ # end
83
+
84
+ # def concat(*others)
85
+ # others.each { |other| self << other }
86
+ # self
87
+ # end
88
+
89
+ # def <<(other)
90
+ # if other
91
+ # raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
92
+ # @end_pos = other.end_pos
93
+ # @source = nil
94
+ # @end_loc = nil
95
+ # end
96
+ # self
97
+ # end
98
+
99
+ # def pred?(loc)
100
+ # loc.is_a?(Location) &&
101
+ # loc.name == name &&
102
+ # loc.start_pos == end_pos
103
+ # end
104
+
105
+ # def to_json(state = _ = nil)
106
+ # {
107
+ # start: {
108
+ # line: start_line,
109
+ # column: start_column
110
+ # },
111
+ # end: {
112
+ # line: end_line,
113
+ # column: end_column
114
+ # },
115
+ # buffer: {
116
+ # name: name&.to_s
117
+ # }
118
+ # }.to_json(state)
119
+ # end
120
+
121
+ # def with_children(required: {}, optional: {})
122
+ # # @type var required: Hash[Symbol, Range[Integer] | Location]
123
+ # # @type var optional: Hash[Symbol, Range[Integer] | Location | nil]
124
+
125
+ # this = WithChildren.new(buffer: buffer, start_pos: start_pos, end_pos: end_pos)
126
+
127
+ # req = required.transform_values do |value|
128
+ # case value
129
+ # when Location
130
+ # value.range
131
+ # else
132
+ # value
133
+ # end
134
+ # end
135
+
136
+ # opt = optional.transform_values do |value|
137
+ # case value
138
+ # when Location
139
+ # value.range
140
+ # else
141
+ # value
142
+ # end
143
+ # end
144
+
145
+ # this.required_children.merge!(req)
146
+ # this.optional_children.merge!(opt)
147
+
148
+ # this
149
+ # end
150
+
151
+ # class WithChildren < Location
152
+ # attr_reader :required_children, :optional_children
153
+
154
+ # def initialize(buffer, start_pos, end_pos)
155
+ # super(buffer, start_pos, end_pos)
156
+
157
+ # @optional_children = {}
158
+ # @required_children = {}
159
+ # end
160
+
161
+ # def initialize_copy(from)
162
+ # required_children.merge!(from.required_children)
163
+ # optional_children.merge!(from.optional_children)
164
+ # self
165
+ # end
166
+
167
+ # def [](key)
168
+ # case
169
+ # when required_children.key?(_ = key)
170
+ # range = required_children[_ = key]
171
+ # Location.new(buffer: buffer, start_pos: range.begin, end_pos: range.end)
172
+ # when optional_children.key?(_ = key)
173
+ # range = required_children[_ = key] || optional_children[_ = key]
174
+ # if range
175
+ # Location.new(buffer: buffer, start_pos: range.begin, end_pos: range.end)
176
+ # end
177
+ # else
178
+ # raise "Unknown key given: `#{key}`"
179
+ # end
180
+ # end
181
+
182
+ # def merge_required(hash)
183
+ # this = dup
184
+
185
+ # h = hash.transform_values do |value|
186
+ # case value
187
+ # when Range
188
+ # value
189
+ # when Location
190
+ # value.range
191
+ # else
192
+ # raise
193
+ # end
194
+ # end
195
+
196
+ # this.required_children.merge!(h)
197
+
198
+ # this
199
+ # end
200
+
201
+ # def merge_optional(hash)
202
+ # this = dup
203
+
204
+ # h = hash.transform_values do |value|
205
+ # case value
206
+ # when Range
207
+ # value
208
+ # when Location
209
+ # value.range
210
+ # else
211
+ # nil
212
+ # end
213
+ # end
214
+
215
+ # this.optional_children.merge!(h)
216
+
217
+ # this
218
+ # end
219
+ # end
220
+ # end
221
+ # end