prism 0.22.0 → 0.24.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -1
  3. data/README.md +2 -1
  4. data/docs/releasing.md +67 -17
  5. data/docs/ruby_parser_translation.md +19 -0
  6. data/docs/serialization.md +2 -0
  7. data/ext/prism/api_node.c +1982 -1538
  8. data/ext/prism/extension.c +12 -7
  9. data/ext/prism/extension.h +2 -2
  10. data/include/prism/diagnostic.h +3 -4
  11. data/include/prism/encoding.h +7 -0
  12. data/include/prism/util/pm_constant_pool.h +1 -1
  13. data/include/prism/util/pm_newline_list.h +4 -3
  14. data/include/prism/util/pm_strpbrk.h +4 -1
  15. data/include/prism/version.h +2 -2
  16. data/lib/prism/desugar_compiler.rb +225 -80
  17. data/lib/prism/dsl.rb +302 -299
  18. data/lib/prism/ffi.rb +103 -77
  19. data/lib/prism/lex_compat.rb +1 -0
  20. data/lib/prism/node.rb +3624 -2114
  21. data/lib/prism/node_ext.rb +25 -2
  22. data/lib/prism/parse_result.rb +56 -19
  23. data/lib/prism/serialize.rb +605 -303
  24. data/lib/prism/translation/parser/compiler.rb +1 -1
  25. data/lib/prism/translation/parser/rubocop.rb +11 -3
  26. data/lib/prism/translation/parser.rb +25 -12
  27. data/lib/prism/translation/parser33.rb +12 -0
  28. data/lib/prism/translation/parser34.rb +12 -0
  29. data/lib/prism/translation/ripper.rb +696 -0
  30. data/lib/prism/translation/ruby_parser.rb +1521 -0
  31. data/lib/prism/translation.rb +3 -3
  32. data/lib/prism.rb +0 -1
  33. data/prism.gemspec +6 -2
  34. data/src/diagnostic.c +10 -11
  35. data/src/encoding.c +16 -17
  36. data/src/options.c +7 -2
  37. data/src/prettyprint.c +3 -3
  38. data/src/prism.c +172 -97
  39. data/src/serialize.c +24 -13
  40. data/src/token_type.c +3 -3
  41. data/src/util/pm_constant_pool.c +1 -1
  42. data/src/util/pm_newline_list.c +6 -3
  43. data/src/util/pm_strpbrk.c +122 -14
  44. metadata +8 -4
  45. data/lib/prism/ripper_compat.rb +0 -285
@@ -94,7 +94,7 @@ module Prism
94
94
 
95
95
  # Returns the full name of this constant. For example: "Foo"
96
96
  def full_name
97
- name.name
97
+ name.to_s
98
98
  end
99
99
  end
100
100
 
@@ -135,7 +135,17 @@ module Prism
135
135
  # Returns the list of parts for the full name of this constant path.
136
136
  # For example: [:Foo, :Bar]
137
137
  def full_name_parts
138
- (parent&.full_name_parts || [:""]).push(child.name)
138
+ parts = case parent
139
+ when ConstantPathNode, ConstantReadNode
140
+ parent.full_name_parts
141
+ when nil
142
+ [:""]
143
+ else
144
+ raise ConstantPathNode::DynamicPartsInConstantPathError,
145
+ "Constant path target contains dynamic parts. Cannot compute full name"
146
+ end
147
+
148
+ parts.push(child.name)
139
149
  end
140
150
 
141
151
  # Returns the full name of this constant path. For example: "Foo::Bar"
@@ -144,6 +154,19 @@ module Prism
144
154
  end
145
155
  end
146
156
 
157
+ class ConstantTargetNode < Node
158
+ # Returns the list of parts for the full name of this constant.
159
+ # For example: [:Foo]
160
+ def full_name_parts
161
+ [name]
162
+ end
163
+
164
+ # Returns the full name of this constant. For example: "Foo"
165
+ def full_name
166
+ name.to_s
167
+ end
168
+ end
169
+
147
170
  class ParametersNode < Node
148
171
  # Mirrors the Method#parameters method.
149
172
  def signature
@@ -9,18 +9,16 @@ module Prism
9
9
  attr_reader :source
10
10
 
11
11
  # The line number where this source starts.
12
- attr_accessor :start_line
12
+ attr_reader :start_line
13
13
 
14
14
  # The list of newline byte offsets in the source code.
15
15
  attr_reader :offsets
16
16
 
17
- # Create a new source object with the given source code and newline byte
18
- # offsets. If no newline byte offsets are given, they will be computed from
19
- # the source code.
20
- def initialize(source, start_line = 1, offsets = compute_offsets(source))
17
+ # Create a new source object with the given source code.
18
+ def initialize(source, start_line = 1, offsets = [])
21
19
  @source = source
22
- @start_line = start_line
23
- @offsets = offsets
20
+ @start_line = start_line # set after parsing is done
21
+ @offsets = offsets # set after parsing is done
24
22
  end
25
23
 
26
24
  # Perform a byteslice on the source code using the given byte offset and
@@ -56,6 +54,23 @@ module Prism
56
54
  character_offset(byte_offset) - character_offset(line_start(byte_offset))
57
55
  end
58
56
 
57
+ # Returns the offset from the start of the file for the given byte offset
58
+ # counting in code units for the given encoding.
59
+ #
60
+ # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
61
+ # concept of code units that differs from the number of characters in other
62
+ # encodings, it is not captured here.
63
+ def code_units_offset(byte_offset, encoding)
64
+ byteslice = source.byteslice(0, byte_offset).encode(encoding)
65
+ (encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length
66
+ end
67
+
68
+ # Returns the column number in code units for the given encoding for the
69
+ # given byte offset.
70
+ def code_units_column(byte_offset, encoding)
71
+ code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
72
+ end
73
+
59
74
  private
60
75
 
61
76
  # Binary search through the offsets to find the line number for the given
@@ -77,14 +92,6 @@ module Prism
77
92
 
78
93
  left - 1
79
94
  end
80
-
81
- # Find all of the newlines in the source code and return their byte offsets
82
- # from the start of the string an array.
83
- def compute_offsets(code)
84
- offsets = [0]
85
- code.b.scan("\n") { offsets << $~.end(0) }
86
- offsets
87
- end
88
95
  end
89
96
 
90
97
  # This represents a location in the source.
@@ -138,6 +145,11 @@ module Prism
138
145
  source.character_offset(start_offset)
139
146
  end
140
147
 
148
+ # The offset from the start of the file in code units of the given encoding.
149
+ def start_code_units_offset(encoding = Encoding::UTF_16LE)
150
+ source.code_units_offset(start_offset, encoding)
151
+ end
152
+
141
153
  # The byte offset from the beginning of the source where this location ends.
142
154
  def end_offset
143
155
  start_offset + length
@@ -149,6 +161,11 @@ module Prism
149
161
  source.character_offset(end_offset)
150
162
  end
151
163
 
164
+ # The offset from the start of the file in code units of the given encoding.
165
+ def end_code_units_offset(encoding = Encoding::UTF_16LE)
166
+ source.code_units_offset(end_offset, encoding)
167
+ end
168
+
152
169
  # The line number where this location starts.
153
170
  def start_line
154
171
  source.line(start_offset)
@@ -177,6 +194,12 @@ module Prism
177
194
  source.character_column(start_offset)
178
195
  end
179
196
 
197
+ # The column number in code units of the given encoding where this location
198
+ # starts from the start of the line.
199
+ def start_code_units_column(encoding = Encoding::UTF_16LE)
200
+ source.code_units_column(start_offset, encoding)
201
+ end
202
+
180
203
  # The column number in bytes where this location ends from the start of the
181
204
  # line.
182
205
  def end_column
@@ -189,6 +212,12 @@ module Prism
189
212
  source.character_column(end_offset)
190
213
  end
191
214
 
215
+ # The column number in code units of the given encoding where this location
216
+ # ends from the start of the line.
217
+ def end_code_units_column(encoding = Encoding::UTF_16LE)
218
+ source.code_units_column(end_offset, encoding)
219
+ end
220
+
192
221
  # Implement the hash pattern matching interface for Location.
193
222
  def deconstruct_keys(keys)
194
223
  { start_offset: start_offset, end_offset: end_offset }
@@ -423,17 +452,19 @@ module Prism
423
452
 
424
453
  # This represents a token from the Ruby source.
425
454
  class Token
455
+ # The Source object that represents the source this token came from.
456
+ attr_reader :source
457
+ private :source
458
+
426
459
  # The type of token that this token is.
427
460
  attr_reader :type
428
461
 
429
462
  # A byteslice of the source that this token represents.
430
463
  attr_reader :value
431
464
 
432
- # A Location object representing the location of this token in the source.
433
- attr_reader :location
434
-
435
465
  # Create a new token object with the given type, value, and location.
436
- def initialize(type, value, location)
466
+ def initialize(source, type, value, location)
467
+ @source = source
437
468
  @type = type
438
469
  @value = value
439
470
  @location = location
@@ -444,6 +475,12 @@ module Prism
444
475
  { type: type, value: value, location: location }
445
476
  end
446
477
 
478
+ # A Location object representing the location of this token in the source.
479
+ def location
480
+ return @location if @location.is_a?(Location)
481
+ @location = Location.new(source, @location >> 32, @location & 0xFFFFFFFF)
482
+ end
483
+
447
484
  # Implement the pretty print interface for Token.
448
485
  def pretty_print(q)
449
486
  q.group do