prism 1.8.1 → 2.0.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +90 -2
- data/Makefile +41 -12
- data/README.md +35 -97
- data/config.yml +174 -163
- data/docs/build_system.md +2 -2
- data/docs/configuration.md +5 -4
- data/docs/encoding.md +2 -2
- data/docs/fuzzing.md +4 -11
- data/docs/javascript.md +19 -4
- data/docs/mapping.md +1 -1
- data/docs/releasing.md +77 -5
- data/docs/relocation.md +2 -4
- data/docs/ripper_translation.md +8 -17
- data/docs/serialization.md +21 -24
- data/docs/testing.md +46 -29
- data/ext/prism/api_node.c +1461 -1401
- data/ext/prism/extconf.rb +3 -4
- data/ext/prism/extension.c +778 -422
- data/ext/prism/extension.h +3 -3
- data/include/prism/arena.h +37 -0
- data/include/prism/ast.h +2729 -612
- data/include/prism/buffer.h +52 -0
- data/include/prism/comments.h +55 -0
- data/include/prism/compiler/accel.h +24 -0
- data/include/prism/compiler/align.h +36 -0
- data/include/prism/compiler/assume.h +25 -0
- data/include/prism/compiler/exported.h +24 -0
- data/include/prism/compiler/fallthrough.h +22 -0
- data/include/prism/compiler/filesystem.h +32 -0
- data/include/prism/compiler/flex_array.h +19 -0
- data/include/prism/compiler/force_inline.h +21 -0
- data/include/prism/compiler/format.h +25 -0
- data/include/prism/compiler/inline.h +17 -0
- data/include/prism/compiler/nodiscard.h +22 -0
- data/include/prism/compiler/nonnull.h +18 -0
- data/include/prism/compiler/unused.h +18 -0
- data/include/prism/constant_pool.h +81 -0
- data/include/prism/diagnostic.h +38 -405
- data/include/prism/errors_format.h +53 -0
- data/include/prism/excludes.h +29 -0
- data/include/prism/integer.h +41 -0
- data/include/prism/internal/allocator.h +68 -0
- data/include/prism/internal/allocator_debug.h +88 -0
- data/include/prism/internal/arena.h +108 -0
- data/include/prism/internal/bit.h +42 -0
- data/include/prism/internal/buffer.h +91 -0
- data/include/prism/internal/char.h +145 -0
- data/include/prism/internal/comments.h +53 -0
- data/include/prism/internal/constant_pool.h +152 -0
- data/include/prism/internal/diagnostic.h +389 -0
- data/include/prism/{encoding.h → internal/encoding.h} +27 -68
- data/include/prism/internal/integer.h +68 -0
- data/include/prism/internal/isinf.h +16 -0
- data/include/prism/internal/line_offset_list.h +34 -0
- data/include/prism/{util/pm_list.h → internal/list.h} +11 -52
- data/include/prism/internal/magic_comments.h +23 -0
- data/include/prism/internal/memchr.h +15 -0
- data/include/prism/internal/node.h +38 -0
- data/include/prism/internal/options.h +232 -0
- data/include/prism/internal/parser.h +984 -0
- data/include/prism/internal/regexp.h +26 -0
- data/include/prism/internal/serialize.h +39 -0
- data/include/prism/internal/source.h +72 -0
- data/include/prism/{static_literals.h → internal/static_literals.h} +26 -47
- data/include/prism/internal/stringy.h +35 -0
- data/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
- data/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
- data/include/prism/internal/tokens.h +11 -0
- data/include/prism/json.h +32 -0
- data/include/prism/line_offset_list.h +61 -0
- data/include/prism/magic_comments.h +35 -0
- data/include/prism/node.h +18 -53
- data/include/prism/options.h +146 -280
- data/include/prism/parser.h +336 -868
- data/include/prism/prettyprint.h +6 -9
- data/include/prism/serialize.h +115 -0
- data/include/prism/source.h +155 -0
- data/include/prism/stream.h +28 -0
- data/include/prism/string_query.h +63 -0
- data/include/prism/stringy.h +72 -0
- data/include/prism/version.h +13 -4
- data/include/prism.h +43 -320
- data/lib/prism/compiler.rb +319 -305
- data/lib/prism/desugar_compiler.rb +105 -34
- data/lib/prism/dispatcher.rb +646 -473
- data/lib/prism/dot_visitor.rb +592 -511
- data/lib/prism/dsl.rb +391 -25
- data/lib/prism/ffi.rb +252 -90
- data/lib/prism/inspect_visitor.rb +357 -325
- data/lib/prism/lex_compat.rb +311 -228
- data/lib/prism/mutation_compiler.rb +313 -305
- data/lib/prism/node.rb +20284 -7038
- data/lib/prism/node_ext.rb +180 -187
- data/lib/prism/node_find.rb +215 -0
- data/lib/prism/parse_result/errors.rb +7 -1
- data/lib/prism/parse_result/newlines.rb +276 -8
- data/lib/prism/parse_result.rb +462 -139
- data/lib/prism/pattern.rb +65 -20
- data/lib/prism/reflection.rb +23 -12
- data/lib/prism/relocation.rb +149 -87
- data/lib/prism/serialize.rb +3442 -536
- data/lib/prism/string_query.rb +16 -1
- data/lib/prism/translation/parser/builder.rb +10 -2
- data/lib/prism/translation/parser/compiler.rb +44 -52
- data/lib/prism/translation/parser/lexer.rb +41 -92
- data/lib/prism/translation/parser.rb +1 -1
- data/lib/prism/translation/parser_current.rb +1 -1
- data/lib/prism/translation/ripper/filter.rb +53 -0
- data/lib/prism/translation/ripper/lexer.rb +92 -5
- data/lib/prism/translation/ripper/sexp.rb +2 -10
- data/lib/prism/translation/ripper/shim.rb +2 -0
- data/lib/prism/translation/ripper.rb +1005 -224
- data/lib/prism/translation/ruby_parser.rb +73 -316
- data/lib/prism/translation.rb +2 -0
- data/lib/prism/visitor.rb +632 -5
- data/lib/prism.rb +79 -22
- data/prism.gemspec +123 -61
- data/rbi/generated/prism/compiler.rbi +489 -0
- data/rbi/generated/prism/desugar_compiler.rbi +306 -0
- data/rbi/generated/prism/dispatcher.rbi +1138 -0
- data/rbi/generated/prism/dot_visitor.rbi +618 -0
- data/rbi/generated/prism/dsl.rbi +751 -0
- data/rbi/generated/prism/inspect_visitor.rbi +503 -0
- data/rbi/generated/prism/lex_compat.rbi +162 -0
- data/rbi/generated/prism/mutation_compiler.rbi +464 -0
- data/rbi/generated/prism/node.rbi +13681 -0
- data/rbi/generated/prism/node_ext.rbi +259 -0
- data/rbi/generated/prism/node_find.rbi +79 -0
- data/rbi/generated/prism/parse_result/errors.rbi +21 -0
- data/rbi/generated/prism/parse_result/newlines.rbi +208 -0
- data/rbi/generated/prism/parse_result.rbi +764 -0
- data/rbi/generated/prism/pattern.rbi +134 -0
- data/rbi/generated/prism/reflection.rbi +89 -0
- data/rbi/generated/prism/relocation.rbi +329 -0
- data/rbi/generated/prism/serialize.rbi +181 -0
- data/rbi/generated/prism/string_query.rbi +36 -0
- data/rbi/generated/prism/translation.rbi +7 -0
- data/rbi/generated/prism/visitor.rbi +650 -0
- data/rbi/generated/prism.rbi +86 -0
- data/rbi/prism/translation/parser_versions.rbi +5 -0
- data/rbi/rubyvm/node_find.rbi +14 -0
- data/sig/generated/prism/compiler.rbs +492 -0
- data/sig/generated/prism/desugar_compiler.rbs +305 -0
- data/sig/generated/prism/dispatcher.rbs +1292 -0
- data/sig/generated/prism/dot_visitor.rbs +635 -0
- data/sig/generated/prism/dsl.rbs +928 -0
- data/sig/generated/prism/inspect_visitor.rbs +509 -0
- data/sig/generated/prism/lex_compat.rbs +166 -0
- data/sig/{prism → generated/prism}/mutation_compiler.rbs +309 -4
- data/sig/generated/prism/node.rbs +20160 -0
- data/sig/generated/prism/node_ext.rbs +290 -0
- data/sig/generated/prism/node_find.rbs +90 -0
- data/sig/generated/prism/parse_result/errors.rbs +22 -0
- data/sig/generated/prism/parse_result/newlines.rbs +223 -0
- data/sig/generated/prism/parse_result.rbs +859 -0
- data/sig/generated/prism/pattern.rbs +156 -0
- data/sig/generated/prism/reflection.rbs +101 -0
- data/sig/generated/prism/relocation.rbs +428 -0
- data/sig/generated/prism/serialize.rbs +195 -0
- data/sig/generated/prism/string_query.rbs +36 -0
- data/sig/generated/prism/translation.rbs +8 -0
- data/sig/generated/prism/visitor.rbs +1111 -0
- data/sig/generated/prism.rbs +84 -0
- data/sig/manifest.yaml +2 -0
- data/src/arena.c +117 -0
- data/src/{util/pm_buffer.c → buffer.c} +44 -21
- data/src/{util/pm_char.c → char.c} +28 -57
- data/src/comments.c +454 -0
- data/src/constant_pool.c +406 -0
- data/src/diagnostic.c +93 -65
- data/src/encoding.c +8 -3
- data/src/errors_format.c +519 -0
- data/src/{util/pm_integer.c → integer.c} +33 -22
- data/src/json.c +5733 -0
- data/src/line_offset_list.c +100 -0
- data/src/list.c +24 -0
- data/src/{util/pm_memchr.c → memchr.c} +8 -6
- data/src/node.c +3504 -7674
- data/src/options.c +162 -49
- data/src/parser.c +349 -0
- data/src/prettyprint.c +421 -354
- data/src/prism.c +8035 -7019
- data/src/regexp.c +961 -45
- data/src/serialize.c +459 -424
- data/src/source.c +518 -0
- data/src/static_literals.c +111 -43
- data/src/string_query.c +166 -0
- data/src/stringy.c +91 -0
- data/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
- data/src/strpbrk.c +447 -0
- data/src/{token_type.c → tokens.c} +39 -18
- metadata +123 -62
- data/ext/prism/api_pack.c +0 -276
- data/include/prism/defines.h +0 -260
- data/include/prism/pack.h +0 -163
- data/include/prism/regexp.h +0 -43
- data/include/prism/util/pm_buffer.h +0 -236
- data/include/prism/util/pm_char.h +0 -204
- data/include/prism/util/pm_constant_pool.h +0 -218
- data/include/prism/util/pm_integer.h +0 -130
- data/include/prism/util/pm_memchr.h +0 -29
- data/include/prism/util/pm_newline_list.h +0 -113
- data/include/prism/util/pm_string.h +0 -200
- data/lib/prism/lex_ripper.rb +0 -64
- data/lib/prism/pack.rb +0 -230
- data/lib/prism/parse_result/comments.rb +0 -188
- data/rbi/prism/compiler.rbi +0 -12
- data/rbi/prism/dsl.rbi +0 -524
- data/rbi/prism/inspect_visitor.rbi +0 -12
- data/rbi/prism/node.rbi +0 -8747
- data/rbi/prism/node_ext.rbi +0 -107
- data/rbi/prism/parse_result.rbi +0 -404
- data/rbi/prism/reflection.rbi +0 -58
- data/rbi/prism/string_query.rbi +0 -12
- data/rbi/prism/visitor.rbi +0 -473
- data/rbi/prism.rbi +0 -66
- data/sig/prism/compiler.rbs +0 -9
- data/sig/prism/dispatcher.rbs +0 -19
- data/sig/prism/dot_visitor.rbs +0 -6
- data/sig/prism/dsl.rbs +0 -351
- data/sig/prism/inspect_visitor.rbs +0 -22
- data/sig/prism/lex_compat.rbs +0 -10
- data/sig/prism/node.rbs +0 -4039
- data/sig/prism/node_ext.rbs +0 -149
- data/sig/prism/pack.rbs +0 -43
- data/sig/prism/parse_result/comments.rbs +0 -38
- data/sig/prism/parse_result.rbs +0 -196
- data/sig/prism/pattern.rbs +0 -13
- data/sig/prism/reflection.rbs +0 -50
- data/sig/prism/relocation.rbs +0 -185
- data/sig/prism/serialize.rbs +0 -8
- data/sig/prism/string_query.rbs +0 -11
- data/sig/prism/visitor.rbs +0 -169
- data/sig/prism.rbs +0 -258
- data/src/pack.c +0 -509
- data/src/util/pm_constant_pool.c +0 -342
- data/src/util/pm_list.c +0 -49
- data/src/util/pm_newline_list.c +0 -125
- data/src/util/pm_string.c +0 -381
- data/src/util/pm_strpbrk.c +0 -206
data/lib/prism/parse_result.rb
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
# :markup: markdown
|
|
3
|
+
#--
|
|
4
|
+
# rbs_inline: enabled
|
|
3
5
|
|
|
4
6
|
module Prism
|
|
7
|
+
# @rbs!
|
|
8
|
+
# # An internal interface for a cache that can be used to compute code
|
|
9
|
+
# # units from byte offsets.
|
|
10
|
+
# interface _CodeUnitsCache
|
|
11
|
+
# def []: (Integer byte_offset) -> Integer
|
|
12
|
+
# end
|
|
13
|
+
|
|
5
14
|
# This represents a source of Ruby code that has been parsed. It is used in
|
|
6
15
|
# conjunction with locations to allow them to resolve line numbers and source
|
|
7
16
|
# ranges.
|
|
@@ -10,14 +19,30 @@ module Prism
|
|
|
10
19
|
# be used instead of `new` and it will return either a `Source` or a
|
|
11
20
|
# specialized and more performant `ASCIISource` if no multibyte characters
|
|
12
21
|
# are present in the source code.
|
|
13
|
-
|
|
22
|
+
#
|
|
23
|
+
# Note that if you are calling this method manually, you will need to supply
|
|
24
|
+
# the start_line and offsets parameters. start_line is the line number that
|
|
25
|
+
# the source starts on, which is typically 1 but can be different if this
|
|
26
|
+
# source is a subset of a larger source or if this is an eval. offsets is an
|
|
27
|
+
# array of byte offsets for the start of each line in the source code, which
|
|
28
|
+
# can be calculated by iterating through the source code and recording the
|
|
29
|
+
# byte offset whenever a newline character is encountered. The first
|
|
30
|
+
# element is always 0 to mark the first line.
|
|
31
|
+
#
|
|
32
|
+
# The comments, comment_attachments, and comment_ranges parameters are the
|
|
33
|
+
# lists described by the attributes of the same names. They are passed in
|
|
34
|
+
# empty when the source is created by the parser and filled in afterward,
|
|
35
|
+
# because the comments themselves refer to the source.
|
|
36
|
+
#
|
|
37
|
+
#: (String source, Integer start_line, Array[Integer] offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges) -> Source
|
|
38
|
+
def self.for(source, start_line, offsets, comments = [], comment_attachments = [], comment_ranges = [])
|
|
14
39
|
if source.ascii_only?
|
|
15
|
-
ASCIISource.new(source, start_line, offsets)
|
|
40
|
+
ASCIISource.new(source, start_line, offsets, comments, comment_attachments, comment_ranges)
|
|
16
41
|
elsif source.encoding == Encoding::BINARY
|
|
17
42
|
source.force_encoding(Encoding::UTF_8)
|
|
18
43
|
|
|
19
44
|
if source.valid_encoding?
|
|
20
|
-
new(source, start_line, offsets)
|
|
45
|
+
new(source, start_line, offsets, comments, comment_attachments, comment_ranges)
|
|
21
46
|
else
|
|
22
47
|
# This is an extremely niche use case where the file is marked as
|
|
23
48
|
# binary, contains multi-byte characters, and those characters are not
|
|
@@ -26,85 +51,162 @@ module Prism
|
|
|
26
51
|
# problems when asking for code units, but it appears to be the
|
|
27
52
|
# cleanest solution at the moment.
|
|
28
53
|
source.force_encoding(Encoding::BINARY)
|
|
29
|
-
ASCIISource.new(source, start_line, offsets)
|
|
54
|
+
ASCIISource.new(source, start_line, offsets, comments, comment_attachments, comment_ranges)
|
|
30
55
|
end
|
|
31
56
|
else
|
|
32
|
-
new(source, start_line, offsets)
|
|
57
|
+
new(source, start_line, offsets, comments, comment_attachments, comment_ranges)
|
|
33
58
|
end
|
|
34
59
|
end
|
|
35
60
|
|
|
36
61
|
# The source code that this source object represents.
|
|
37
|
-
attr_reader :source
|
|
62
|
+
attr_reader :source #: String
|
|
38
63
|
|
|
39
64
|
# The line number where this source starts.
|
|
40
|
-
attr_reader :start_line
|
|
41
|
-
|
|
42
|
-
# The list of
|
|
43
|
-
|
|
65
|
+
attr_reader :start_line #: Integer
|
|
66
|
+
|
|
67
|
+
# The list of comments that were encountered during parsing. When the source
|
|
68
|
+
# is parsed with the attach_comments option, these are sorted by start
|
|
69
|
+
# offset.
|
|
70
|
+
attr_reader :comments #: Array[Comment]
|
|
71
|
+
|
|
72
|
+
# The comments attached to nodes, grouped by node in order of node id. This
|
|
73
|
+
# is empty unless the source was parsed with the attach_comments option.
|
|
74
|
+
attr_reader :comment_attachments #: Array[Comment]
|
|
75
|
+
|
|
76
|
+
# Indices into comment_attachments, indexed by node id. For each node that
|
|
77
|
+
# owns comments, the index at which its comments begin is stored at its node
|
|
78
|
+
# id and the index at which they end is stored at the following node id. The
|
|
79
|
+
# other entries are nil. This is empty unless the source was parsed with the
|
|
80
|
+
# attach_comments option.
|
|
81
|
+
attr_reader :comment_ranges #: Array[Integer?]
|
|
82
|
+
|
|
83
|
+
# The list of newline byte offsets in the source code. When initialized from
|
|
84
|
+
# the C extension, this may be a packed binary string of uint32_t values
|
|
85
|
+
# that is lazily unpacked on first access.
|
|
86
|
+
#
|
|
87
|
+
#: () -> Array[Integer]
|
|
88
|
+
def offsets
|
|
89
|
+
offsets = @offsets
|
|
90
|
+
return offsets if offsets.is_a?(Array)
|
|
91
|
+
@offsets = offsets.unpack("L*")
|
|
92
|
+
end
|
|
44
93
|
|
|
45
|
-
# Create a new source object with the given source code.
|
|
46
|
-
|
|
94
|
+
# Create a new source object with the given source code. The offsets
|
|
95
|
+
# parameter can be either an Array of Integer byte offsets or a packed
|
|
96
|
+
# binary string of uint32_t values (from the C extension).
|
|
97
|
+
#
|
|
98
|
+
#: (String source, Integer start_line, Array[Integer] | String offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges) -> void
|
|
99
|
+
def initialize(source, start_line, offsets, comments = [], comment_attachments = [], comment_ranges = [])
|
|
47
100
|
@source = source
|
|
48
|
-
@start_line = start_line
|
|
49
|
-
@offsets = offsets
|
|
101
|
+
@start_line = start_line
|
|
102
|
+
@offsets = offsets
|
|
103
|
+
@comments = comments
|
|
104
|
+
@comment_attachments = comment_attachments
|
|
105
|
+
@comment_ranges = comment_ranges
|
|
50
106
|
end
|
|
51
107
|
|
|
52
108
|
# Replace the value of start_line with the given value.
|
|
109
|
+
#
|
|
110
|
+
#: (Integer start_line) -> void
|
|
53
111
|
def replace_start_line(start_line)
|
|
54
112
|
@start_line = start_line
|
|
55
113
|
end
|
|
56
114
|
|
|
57
115
|
# Replace the value of offsets with the given value.
|
|
116
|
+
#
|
|
117
|
+
#: (Array[Integer] offsets) -> void
|
|
58
118
|
def replace_offsets(offsets)
|
|
59
|
-
@offsets
|
|
119
|
+
@offsets = offsets
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# The comments attached to the node with the given id, ordered by start
|
|
123
|
+
# offset. Comments are only attached when the source is parsed with the
|
|
124
|
+
# attach_comments option.
|
|
125
|
+
#
|
|
126
|
+
#: (Integer node_id) -> Array[Comment]
|
|
127
|
+
def comments_for(node_id)
|
|
128
|
+
start = comment_ranges[node_id]
|
|
129
|
+
finish = comment_ranges[node_id + 1]
|
|
130
|
+
return [] if start.nil? || finish.nil?
|
|
131
|
+
|
|
132
|
+
comment_attachments[start...finish] || []
|
|
60
133
|
end
|
|
61
134
|
|
|
62
135
|
# Returns the encoding of the source code, which is set by parameters to the
|
|
63
136
|
# parser or by the encoding magic comment.
|
|
137
|
+
#
|
|
138
|
+
#: () -> Encoding
|
|
64
139
|
def encoding
|
|
65
140
|
source.encoding
|
|
66
141
|
end
|
|
67
142
|
|
|
68
143
|
# Returns the lines of the source code as an array of strings.
|
|
144
|
+
#
|
|
145
|
+
#: () -> Array[String]
|
|
69
146
|
def lines
|
|
70
147
|
source.lines
|
|
71
148
|
end
|
|
72
149
|
|
|
73
150
|
# Perform a byteslice on the source code using the given byte offset and
|
|
74
151
|
# byte length.
|
|
152
|
+
#
|
|
153
|
+
#: (Integer byte_offset, Integer length) -> String
|
|
75
154
|
def slice(byte_offset, length)
|
|
76
155
|
source.byteslice(byte_offset, length) or raise
|
|
77
156
|
end
|
|
78
157
|
|
|
158
|
+
# Converts the line number and column in bytes to a byte offset.
|
|
159
|
+
#
|
|
160
|
+
#: (Integer line, Integer column) -> Integer
|
|
161
|
+
def byte_offset(line, column)
|
|
162
|
+
normal = line - @start_line
|
|
163
|
+
raise IndexError if normal < 0
|
|
164
|
+
offsets.fetch(normal) + column
|
|
165
|
+
rescue IndexError
|
|
166
|
+
raise ArgumentError, "line #{line} is out of range"
|
|
167
|
+
end
|
|
168
|
+
|
|
79
169
|
# Binary search through the offsets to find the line number for the given
|
|
80
170
|
# byte offset.
|
|
171
|
+
#
|
|
172
|
+
#: (Integer byte_offset) -> Integer
|
|
81
173
|
def line(byte_offset)
|
|
82
174
|
start_line + find_line(byte_offset)
|
|
83
175
|
end
|
|
84
176
|
|
|
85
177
|
# Return the byte offset of the start of the line corresponding to the given
|
|
86
178
|
# byte offset.
|
|
179
|
+
#
|
|
180
|
+
#: (Integer byte_offset) -> Integer
|
|
87
181
|
def line_start(byte_offset)
|
|
88
182
|
offsets[find_line(byte_offset)]
|
|
89
183
|
end
|
|
90
184
|
|
|
91
185
|
# Returns the byte offset of the end of the line corresponding to the given
|
|
92
186
|
# byte offset.
|
|
187
|
+
#
|
|
188
|
+
#: (Integer byte_offset) -> Integer
|
|
93
189
|
def line_end(byte_offset)
|
|
94
190
|
offsets[find_line(byte_offset) + 1] || source.bytesize
|
|
95
191
|
end
|
|
96
192
|
|
|
97
|
-
# Return the column
|
|
193
|
+
# Return the column in bytes for the given byte offset.
|
|
194
|
+
#
|
|
195
|
+
#: (Integer byte_offset) -> Integer
|
|
98
196
|
def column(byte_offset)
|
|
99
197
|
byte_offset - line_start(byte_offset)
|
|
100
198
|
end
|
|
101
199
|
|
|
102
200
|
# Return the character offset for the given byte offset.
|
|
201
|
+
#
|
|
202
|
+
#: (Integer byte_offset) -> Integer
|
|
103
203
|
def character_offset(byte_offset)
|
|
104
204
|
(source.byteslice(0, byte_offset) or raise).length
|
|
105
205
|
end
|
|
106
206
|
|
|
107
|
-
# Return the column
|
|
207
|
+
# Return the column in characters for the given byte offset.
|
|
208
|
+
#
|
|
209
|
+
#: (Integer byte_offset) -> Integer
|
|
108
210
|
def character_column(byte_offset)
|
|
109
211
|
character_offset(byte_offset) - character_offset(line_start(byte_offset))
|
|
110
212
|
end
|
|
@@ -121,7 +223,11 @@ module Prism
|
|
|
121
223
|
# possible that the given byte offset will not occur on a character
|
|
122
224
|
# boundary. Second, it's possible that the source code will contain a
|
|
123
225
|
# character that has no equivalent in the given encoding.
|
|
226
|
+
#
|
|
227
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
124
228
|
def code_units_offset(byte_offset, encoding)
|
|
229
|
+
return byte_offset if encoding == Encoding::UTF_8
|
|
230
|
+
|
|
125
231
|
byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace)
|
|
126
232
|
|
|
127
233
|
if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE
|
|
@@ -133,28 +239,37 @@ module Prism
|
|
|
133
239
|
|
|
134
240
|
# Generate a cache that targets a specific encoding for calculating code
|
|
135
241
|
# unit offsets.
|
|
242
|
+
#
|
|
243
|
+
#: (Encoding encoding) -> CodeUnitsCache
|
|
136
244
|
def code_units_cache(encoding)
|
|
137
245
|
CodeUnitsCache.new(source, encoding)
|
|
138
246
|
end
|
|
139
247
|
|
|
140
|
-
# Returns the column
|
|
248
|
+
# Returns the column in code units for the given encoding for the
|
|
141
249
|
# given byte offset.
|
|
250
|
+
#
|
|
251
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
142
252
|
def code_units_column(byte_offset, encoding)
|
|
143
253
|
code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
|
|
144
254
|
end
|
|
145
255
|
|
|
146
256
|
# Freeze this object and the objects it contains.
|
|
257
|
+
#
|
|
258
|
+
#: () -> void
|
|
147
259
|
def deep_freeze
|
|
148
260
|
source.freeze
|
|
149
261
|
offsets.freeze
|
|
262
|
+
comments.freeze
|
|
263
|
+
comment_attachments.freeze
|
|
264
|
+
comment_ranges.freeze
|
|
150
265
|
freeze
|
|
151
266
|
end
|
|
152
267
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
# Binary search through the offsets to find the line number for the given
|
|
268
|
+
# Binary search through the offsets to find the index for the given
|
|
156
269
|
# byte offset.
|
|
157
|
-
|
|
270
|
+
#
|
|
271
|
+
#: (Integer byte_offset) -> Integer
|
|
272
|
+
def find_line(byte_offset) # :nodoc:
|
|
158
273
|
index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length
|
|
159
274
|
index - 1
|
|
160
275
|
end
|
|
@@ -175,38 +290,69 @@ module Prism
|
|
|
175
290
|
# has not yet been implemented.
|
|
176
291
|
#
|
|
177
292
|
class CodeUnitsCache
|
|
293
|
+
# Counter used for UTF-8, where one code unit equals one byte.
|
|
294
|
+
class UTF8Counter # :nodoc:
|
|
295
|
+
#: (Integer byte_offset, Integer byte_length) -> Integer
|
|
296
|
+
def count(byte_offset, byte_length)
|
|
297
|
+
byte_length
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
178
301
|
class UTF16Counter # :nodoc:
|
|
302
|
+
# @rbs @source: String
|
|
303
|
+
# @rbs @encoding: Encoding
|
|
304
|
+
|
|
305
|
+
#: (String source, Encoding encoding) -> void
|
|
179
306
|
def initialize(source, encoding)
|
|
180
307
|
@source = source
|
|
181
308
|
@encoding = encoding
|
|
182
309
|
end
|
|
183
310
|
|
|
311
|
+
#: (Integer byte_offset, Integer byte_length) -> Integer
|
|
184
312
|
def count(byte_offset, byte_length)
|
|
185
|
-
@source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2
|
|
313
|
+
(@source.byteslice(byte_offset, byte_length) or raise).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2
|
|
186
314
|
end
|
|
187
315
|
end
|
|
188
316
|
|
|
189
|
-
|
|
317
|
+
# Counter used for UTF-32, where one code unit equals one code point and
|
|
318
|
+
# matches String#length. Also used as a best-effort fallback for any other
|
|
319
|
+
# encoding that does not have a dedicated counter.
|
|
320
|
+
class UTF32Counter # :nodoc:
|
|
321
|
+
# @rbs @source: String
|
|
322
|
+
# @rbs @encoding: Encoding
|
|
323
|
+
|
|
324
|
+
#: (String source, Encoding encoding) -> void
|
|
190
325
|
def initialize(source, encoding)
|
|
191
326
|
@source = source
|
|
192
327
|
@encoding = encoding
|
|
193
328
|
end
|
|
194
329
|
|
|
330
|
+
#: (Integer byte_offset, Integer byte_length) -> Integer
|
|
195
331
|
def count(byte_offset, byte_length)
|
|
196
|
-
@source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).length
|
|
332
|
+
(@source.byteslice(byte_offset, byte_length) or raise).encode(@encoding, invalid: :replace, undef: :replace).length
|
|
197
333
|
end
|
|
198
334
|
end
|
|
199
335
|
|
|
200
|
-
private_constant :UTF16Counter, :
|
|
336
|
+
private_constant :UTF8Counter, :UTF16Counter, :UTF32Counter
|
|
337
|
+
|
|
338
|
+
# @rbs @source: String
|
|
339
|
+
# @rbs @counter: UTF8Counter | UTF16Counter | UTF32Counter
|
|
340
|
+
# @rbs @cache: Hash[Integer, Integer]
|
|
341
|
+
# @rbs @offsets: Array[Integer]
|
|
201
342
|
|
|
202
343
|
# Initialize a new cache with the given source and encoding.
|
|
344
|
+
#
|
|
345
|
+
#: (String source, Encoding encoding) -> void
|
|
203
346
|
def initialize(source, encoding)
|
|
204
347
|
@source = source
|
|
205
348
|
@counter =
|
|
206
|
-
|
|
349
|
+
case encoding
|
|
350
|
+
when Encoding::UTF_8
|
|
351
|
+
UTF8Counter.new
|
|
352
|
+
when Encoding::UTF_16LE, Encoding::UTF_16BE
|
|
207
353
|
UTF16Counter.new(source, encoding)
|
|
208
354
|
else
|
|
209
|
-
|
|
355
|
+
UTF32Counter.new(source, encoding)
|
|
210
356
|
end
|
|
211
357
|
|
|
212
358
|
@cache = {} #: Hash[Integer, Integer]
|
|
@@ -214,6 +360,8 @@ module Prism
|
|
|
214
360
|
end
|
|
215
361
|
|
|
216
362
|
# Retrieve the code units offset from the given byte offset.
|
|
363
|
+
#
|
|
364
|
+
#: (Integer byte_offset) -> Integer
|
|
217
365
|
def [](byte_offset)
|
|
218
366
|
@cache[byte_offset] ||=
|
|
219
367
|
if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil?
|
|
@@ -240,11 +388,15 @@ module Prism
|
|
|
240
388
|
# at that point we will treat everything as single-byte characters.
|
|
241
389
|
class ASCIISource < Source
|
|
242
390
|
# Return the character offset for the given byte offset.
|
|
391
|
+
#
|
|
392
|
+
#: (Integer byte_offset) -> Integer
|
|
243
393
|
def character_offset(byte_offset)
|
|
244
394
|
byte_offset
|
|
245
395
|
end
|
|
246
396
|
|
|
247
|
-
# Return the column
|
|
397
|
+
# Return the column in characters for the given byte offset.
|
|
398
|
+
#
|
|
399
|
+
#: (Integer byte_offset) -> Integer
|
|
248
400
|
def character_column(byte_offset)
|
|
249
401
|
byte_offset - line_start(byte_offset)
|
|
250
402
|
end
|
|
@@ -255,6 +407,8 @@ module Prism
|
|
|
255
407
|
# This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
|
|
256
408
|
# concept of code units that differs from the number of characters in other
|
|
257
409
|
# encodings, it is not captured here.
|
|
410
|
+
#
|
|
411
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
258
412
|
def code_units_offset(byte_offset, encoding)
|
|
259
413
|
byte_offset
|
|
260
414
|
end
|
|
@@ -262,6 +416,8 @@ module Prism
|
|
|
262
416
|
# Returns a cache that is the identity function in order to maintain the
|
|
263
417
|
# same interface. We can do this because code units are always equivalent to
|
|
264
418
|
# byte offsets for ASCII-only sources.
|
|
419
|
+
#
|
|
420
|
+
#: (Encoding encoding) -> _CodeUnitsCache
|
|
265
421
|
def code_units_cache(encoding)
|
|
266
422
|
->(byte_offset) { byte_offset }
|
|
267
423
|
end
|
|
@@ -269,6 +425,8 @@ module Prism
|
|
|
269
425
|
# Specialized version of `code_units_column` that does not depend on
|
|
270
426
|
# `code_units_offset`, which is a more expensive operation. This is
|
|
271
427
|
# essentially the same as `Prism::Source#column`.
|
|
428
|
+
#
|
|
429
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
272
430
|
def code_units_column(byte_offset, encoding)
|
|
273
431
|
byte_offset - line_start(byte_offset)
|
|
274
432
|
end
|
|
@@ -278,79 +436,57 @@ module Prism
|
|
|
278
436
|
class Location
|
|
279
437
|
# A Source object that is used to determine more information from the given
|
|
280
438
|
# offset and length.
|
|
281
|
-
attr_reader :source
|
|
439
|
+
attr_reader :source #: Source
|
|
282
440
|
protected :source
|
|
283
441
|
|
|
284
442
|
# The byte offset from the beginning of the source where this location
|
|
285
443
|
# starts.
|
|
286
|
-
attr_reader :start_offset
|
|
444
|
+
attr_reader :start_offset #: Integer
|
|
287
445
|
|
|
288
446
|
# The length of this location in bytes.
|
|
289
|
-
attr_reader :length
|
|
447
|
+
attr_reader :length #: Integer
|
|
290
448
|
|
|
291
449
|
# Create a new location object with the given source, start byte offset, and
|
|
292
450
|
# byte length.
|
|
451
|
+
#
|
|
452
|
+
#: (Source source, Integer start_offset, Integer length) -> void
|
|
293
453
|
def initialize(source, start_offset, length)
|
|
294
454
|
@source = source
|
|
295
455
|
@start_offset = start_offset
|
|
296
456
|
@length = length
|
|
297
|
-
|
|
298
|
-
# These are used to store comments that are associated with this location.
|
|
299
|
-
# They are initialized to `nil` to save on memory when there are no
|
|
300
|
-
# comments to be attached and/or the comment-related APIs are not used.
|
|
301
|
-
@leading_comments = nil
|
|
302
|
-
@trailing_comments = nil
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
# These are the comments that are associated with this location that exist
|
|
306
|
-
# before the start of this location.
|
|
307
|
-
def leading_comments
|
|
308
|
-
@leading_comments ||= []
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
# Attach a comment to the leading comments of this location.
|
|
312
|
-
def leading_comment(comment)
|
|
313
|
-
leading_comments << comment
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
# These are the comments that are associated with this location that exist
|
|
317
|
-
# after the end of this location.
|
|
318
|
-
def trailing_comments
|
|
319
|
-
@trailing_comments ||= []
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
# Attach a comment to the trailing comments of this location.
|
|
323
|
-
def trailing_comment(comment)
|
|
324
|
-
trailing_comments << comment
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
# Returns all comments that are associated with this location (both leading
|
|
328
|
-
# and trailing comments).
|
|
329
|
-
def comments
|
|
330
|
-
[*@leading_comments, *@trailing_comments]
|
|
331
457
|
end
|
|
332
458
|
|
|
333
459
|
# Create a new location object with the given options.
|
|
460
|
+
#
|
|
461
|
+
#: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location
|
|
334
462
|
def copy(source: self.source, start_offset: self.start_offset, length: self.length)
|
|
335
463
|
Location.new(source, start_offset, length)
|
|
336
464
|
end
|
|
337
465
|
|
|
338
466
|
# Returns a new location that is the result of chopping off the last byte.
|
|
467
|
+
#
|
|
468
|
+
#: () -> Location
|
|
339
469
|
def chop
|
|
340
470
|
copy(length: length == 0 ? length : length - 1)
|
|
341
471
|
end
|
|
342
472
|
|
|
343
473
|
# Returns a string representation of this location.
|
|
344
|
-
|
|
474
|
+
#
|
|
475
|
+
#: () -> String
|
|
476
|
+
def inspect # :nodoc:
|
|
345
477
|
"#<Prism::Location @start_offset=#{@start_offset} @length=#{@length} start_line=#{start_line}>"
|
|
346
478
|
end
|
|
347
479
|
|
|
348
480
|
# Returns all of the lines of the source code associated with this location.
|
|
481
|
+
#
|
|
482
|
+
#: () -> Array[String]
|
|
349
483
|
def source_lines
|
|
350
484
|
source.lines
|
|
351
485
|
end
|
|
352
486
|
|
|
353
487
|
# The source code that this location represents.
|
|
488
|
+
#
|
|
489
|
+
#: () -> String
|
|
354
490
|
def slice
|
|
355
491
|
source.slice(start_offset, length)
|
|
356
492
|
end
|
|
@@ -358,6 +494,8 @@ module Prism
|
|
|
358
494
|
# The source code that this location represents starting from the beginning
|
|
359
495
|
# of the line that this location starts on to the end of the line that this
|
|
360
496
|
# location ends on.
|
|
497
|
+
#
|
|
498
|
+
#: () -> String
|
|
361
499
|
def slice_lines
|
|
362
500
|
line_start = source.line_start(start_offset)
|
|
363
501
|
line_end = source.line_end(end_offset)
|
|
@@ -366,118 +504,160 @@ module Prism
|
|
|
366
504
|
|
|
367
505
|
# The character offset from the beginning of the source where this location
|
|
368
506
|
# starts.
|
|
507
|
+
#
|
|
508
|
+
#: () -> Integer
|
|
369
509
|
def start_character_offset
|
|
370
510
|
source.character_offset(start_offset)
|
|
371
511
|
end
|
|
372
512
|
|
|
373
513
|
# The offset from the start of the file in code units of the given encoding.
|
|
514
|
+
#
|
|
515
|
+
#: (Encoding encoding) -> Integer
|
|
374
516
|
def start_code_units_offset(encoding = Encoding::UTF_16LE)
|
|
375
517
|
source.code_units_offset(start_offset, encoding)
|
|
376
518
|
end
|
|
377
519
|
|
|
378
520
|
# The start offset from the start of the file in code units using the given
|
|
379
521
|
# cache to fetch or calculate the value.
|
|
522
|
+
#
|
|
523
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
380
524
|
def cached_start_code_units_offset(cache)
|
|
381
525
|
cache[start_offset]
|
|
382
526
|
end
|
|
383
527
|
|
|
384
528
|
# The byte offset from the beginning of the source where this location ends.
|
|
529
|
+
#
|
|
530
|
+
#: () -> Integer
|
|
385
531
|
def end_offset
|
|
386
532
|
start_offset + length
|
|
387
533
|
end
|
|
388
534
|
|
|
389
535
|
# The character offset from the beginning of the source where this location
|
|
390
536
|
# ends.
|
|
537
|
+
#
|
|
538
|
+
#: () -> Integer
|
|
391
539
|
def end_character_offset
|
|
392
540
|
source.character_offset(end_offset)
|
|
393
541
|
end
|
|
394
542
|
|
|
395
543
|
# The offset from the start of the file in code units of the given encoding.
|
|
544
|
+
#
|
|
545
|
+
#: (Encoding encoding) -> Integer
|
|
396
546
|
def end_code_units_offset(encoding = Encoding::UTF_16LE)
|
|
397
547
|
source.code_units_offset(end_offset, encoding)
|
|
398
548
|
end
|
|
399
549
|
|
|
400
550
|
# The end offset from the start of the file in code units using the given
|
|
401
551
|
# cache to fetch or calculate the value.
|
|
552
|
+
#
|
|
553
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
402
554
|
def cached_end_code_units_offset(cache)
|
|
403
555
|
cache[end_offset]
|
|
404
556
|
end
|
|
405
557
|
|
|
406
558
|
# The line number where this location starts.
|
|
559
|
+
#
|
|
560
|
+
#: () -> Integer
|
|
407
561
|
def start_line
|
|
408
562
|
source.line(start_offset)
|
|
409
563
|
end
|
|
410
564
|
|
|
411
565
|
# The content of the line where this location starts before this location.
|
|
566
|
+
#
|
|
567
|
+
#: () -> String
|
|
412
568
|
def start_line_slice
|
|
413
569
|
offset = source.line_start(start_offset)
|
|
414
570
|
source.slice(offset, start_offset - offset)
|
|
415
571
|
end
|
|
416
572
|
|
|
417
573
|
# The line number where this location ends.
|
|
574
|
+
#
|
|
575
|
+
#: () -> Integer
|
|
418
576
|
def end_line
|
|
419
577
|
source.line(end_offset)
|
|
420
578
|
end
|
|
421
579
|
|
|
422
|
-
# The column
|
|
580
|
+
# The column in bytes where this location starts from the start of
|
|
423
581
|
# the line.
|
|
582
|
+
#
|
|
583
|
+
#: () -> Integer
|
|
424
584
|
def start_column
|
|
425
585
|
source.column(start_offset)
|
|
426
586
|
end
|
|
427
587
|
|
|
428
|
-
# The column
|
|
588
|
+
# The column in characters where this location ends from the start of
|
|
429
589
|
# the line.
|
|
590
|
+
#
|
|
591
|
+
#: () -> Integer
|
|
430
592
|
def start_character_column
|
|
431
593
|
source.character_column(start_offset)
|
|
432
594
|
end
|
|
433
595
|
|
|
434
|
-
# The column
|
|
596
|
+
# The column in code units of the given encoding where this location
|
|
435
597
|
# starts from the start of the line.
|
|
598
|
+
#
|
|
599
|
+
#: (?Encoding encoding) -> Integer
|
|
436
600
|
def start_code_units_column(encoding = Encoding::UTF_16LE)
|
|
437
601
|
source.code_units_column(start_offset, encoding)
|
|
438
602
|
end
|
|
439
603
|
|
|
440
604
|
# The start column in code units using the given cache to fetch or calculate
|
|
441
605
|
# the value.
|
|
606
|
+
#
|
|
607
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
442
608
|
def cached_start_code_units_column(cache)
|
|
443
609
|
cache[start_offset] - cache[source.line_start(start_offset)]
|
|
444
610
|
end
|
|
445
611
|
|
|
446
|
-
# The column
|
|
612
|
+
# The column in bytes where this location ends from the start of the
|
|
447
613
|
# line.
|
|
614
|
+
#
|
|
615
|
+
#: () -> Integer
|
|
448
616
|
def end_column
|
|
449
617
|
source.column(end_offset)
|
|
450
618
|
end
|
|
451
619
|
|
|
452
|
-
# The column
|
|
620
|
+
# The column in characters where this location ends from the start of
|
|
453
621
|
# the line.
|
|
622
|
+
#
|
|
623
|
+
#: () -> Integer
|
|
454
624
|
def end_character_column
|
|
455
625
|
source.character_column(end_offset)
|
|
456
626
|
end
|
|
457
627
|
|
|
458
|
-
# The column
|
|
628
|
+
# The column in code units of the given encoding where this location
|
|
459
629
|
# ends from the start of the line.
|
|
630
|
+
#
|
|
631
|
+
#: (?Encoding encoding) -> Integer
|
|
460
632
|
def end_code_units_column(encoding = Encoding::UTF_16LE)
|
|
461
633
|
source.code_units_column(end_offset, encoding)
|
|
462
634
|
end
|
|
463
635
|
|
|
464
636
|
# The end column in code units using the given cache to fetch or calculate
|
|
465
637
|
# the value.
|
|
638
|
+
#
|
|
639
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
466
640
|
def cached_end_code_units_column(cache)
|
|
467
641
|
cache[end_offset] - cache[source.line_start(end_offset)]
|
|
468
642
|
end
|
|
469
643
|
|
|
470
644
|
# Implement the hash pattern matching interface for Location.
|
|
471
|
-
|
|
645
|
+
#
|
|
646
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
647
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
472
648
|
{ start_offset: start_offset, end_offset: end_offset }
|
|
473
649
|
end
|
|
474
650
|
|
|
475
651
|
# Implement the pretty print interface for Location.
|
|
476
|
-
|
|
652
|
+
#
|
|
653
|
+
#: (PP q) -> void
|
|
654
|
+
def pretty_print(q) # :nodoc:
|
|
477
655
|
q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})")
|
|
478
656
|
end
|
|
479
657
|
|
|
480
658
|
# Returns true if the given other location is equal to this location.
|
|
659
|
+
#
|
|
660
|
+
#: (untyped other) -> bool
|
|
481
661
|
def ==(other)
|
|
482
662
|
Location === other &&
|
|
483
663
|
other.start_offset == start_offset &&
|
|
@@ -487,6 +667,8 @@ module Prism
|
|
|
487
667
|
# Returns a new location that stretches from this location to the given
|
|
488
668
|
# other location. Raises an error if this location is not before the other
|
|
489
669
|
# location or if they don't share the same source.
|
|
670
|
+
#
|
|
671
|
+
#: (Location other) -> Location
|
|
490
672
|
def join(other)
|
|
491
673
|
raise "Incompatible sources" if source != other.source
|
|
492
674
|
raise "Incompatible locations" if start_offset > other.start_offset
|
|
@@ -497,6 +679,8 @@ module Prism
|
|
|
497
679
|
# Join this location with the first occurrence of the string in the source
|
|
498
680
|
# that occurs after this location on the same line, and return the new
|
|
499
681
|
# location. This will raise an error if the string does not exist.
|
|
682
|
+
#
|
|
683
|
+
#: (String string) -> Location
|
|
500
684
|
def adjoin(string)
|
|
501
685
|
line_suffix = source.slice(end_offset, source.line_end(end_offset) - end_offset)
|
|
502
686
|
|
|
@@ -510,23 +694,38 @@ module Prism
|
|
|
510
694
|
# This represents a comment that was encountered during parsing. It is the
|
|
511
695
|
# base class for all comment types.
|
|
512
696
|
class Comment
|
|
513
|
-
# The
|
|
514
|
-
attr_reader :location
|
|
697
|
+
# The Location of this comment in the source.
|
|
698
|
+
attr_reader :location #: Location
|
|
515
699
|
|
|
516
700
|
# Create a new comment object with the given location.
|
|
701
|
+
#
|
|
702
|
+
#: (Location location) -> void
|
|
517
703
|
def initialize(location)
|
|
518
704
|
@location = location
|
|
519
705
|
end
|
|
520
706
|
|
|
521
707
|
# Implement the hash pattern matching interface for Comment.
|
|
522
|
-
|
|
708
|
+
#
|
|
709
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
710
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
523
711
|
{ location: location }
|
|
524
712
|
end
|
|
525
713
|
|
|
526
714
|
# Returns the content of the comment by slicing it from the source code.
|
|
715
|
+
#
|
|
716
|
+
#: () -> String
|
|
527
717
|
def slice
|
|
528
718
|
location.slice
|
|
529
719
|
end
|
|
720
|
+
|
|
721
|
+
# Returns true if this comment happens on the same line as other code and
|
|
722
|
+
# false if the comment is by itself. This can only be true for inline
|
|
723
|
+
# comments and should be false for block comments.
|
|
724
|
+
#
|
|
725
|
+
#: () -> bool
|
|
726
|
+
def trailing?
|
|
727
|
+
raise NotImplementedError, "trailing? is not implemented for #{self.class}"
|
|
728
|
+
end
|
|
530
729
|
end
|
|
531
730
|
|
|
532
731
|
# InlineComment objects are the most common. They correspond to comments in
|
|
@@ -534,12 +733,18 @@ module Prism
|
|
|
534
733
|
class InlineComment < Comment
|
|
535
734
|
# Returns true if this comment happens on the same line as other code and
|
|
536
735
|
# false if the comment is by itself.
|
|
736
|
+
#
|
|
737
|
+
#: () -> bool
|
|
537
738
|
def trailing?
|
|
538
739
|
!location.start_line_slice.strip.empty?
|
|
740
|
+
rescue ArgumentError # invalid bytes, never whitespace only
|
|
741
|
+
false
|
|
539
742
|
end
|
|
540
743
|
|
|
541
744
|
# Returns a string representation of this comment.
|
|
542
|
-
|
|
745
|
+
#
|
|
746
|
+
#: () -> String
|
|
747
|
+
def inspect # :nodoc:
|
|
543
748
|
"#<Prism::InlineComment @location=#{location.inspect}>"
|
|
544
749
|
end
|
|
545
750
|
end
|
|
@@ -547,13 +752,17 @@ module Prism
|
|
|
547
752
|
# EmbDocComment objects correspond to comments that are surrounded by =begin
|
|
548
753
|
# and =end.
|
|
549
754
|
class EmbDocComment < Comment
|
|
550
|
-
# This can only be true for inline comments.
|
|
755
|
+
# Returns false. This can only be true for inline comments.
|
|
756
|
+
#
|
|
757
|
+
#: () -> bool
|
|
551
758
|
def trailing?
|
|
552
759
|
false
|
|
553
760
|
end
|
|
554
761
|
|
|
555
762
|
# Returns a string representation of this comment.
|
|
556
|
-
|
|
763
|
+
#
|
|
764
|
+
#: () -> String
|
|
765
|
+
def inspect # :nodoc:
|
|
557
766
|
"#<Prism::EmbDocComment @location=#{location.inspect}>"
|
|
558
767
|
end
|
|
559
768
|
end
|
|
@@ -561,34 +770,44 @@ module Prism
|
|
|
561
770
|
# This represents a magic comment that was encountered during parsing.
|
|
562
771
|
class MagicComment
|
|
563
772
|
# A Location object representing the location of the key in the source.
|
|
564
|
-
attr_reader :key_loc
|
|
773
|
+
attr_reader :key_loc #: Location
|
|
565
774
|
|
|
566
775
|
# A Location object representing the location of the value in the source.
|
|
567
|
-
attr_reader :value_loc
|
|
776
|
+
attr_reader :value_loc #: Location
|
|
568
777
|
|
|
569
778
|
# Create a new magic comment object with the given key and value locations.
|
|
779
|
+
#
|
|
780
|
+
#: (Location key_loc, Location value_loc) -> void
|
|
570
781
|
def initialize(key_loc, value_loc)
|
|
571
782
|
@key_loc = key_loc
|
|
572
783
|
@value_loc = value_loc
|
|
573
784
|
end
|
|
574
785
|
|
|
575
786
|
# Returns the key of the magic comment by slicing it from the source code.
|
|
787
|
+
#
|
|
788
|
+
#: () -> String
|
|
576
789
|
def key
|
|
577
790
|
key_loc.slice
|
|
578
791
|
end
|
|
579
792
|
|
|
580
793
|
# Returns the value of the magic comment by slicing it from the source code.
|
|
794
|
+
#
|
|
795
|
+
#: () -> String
|
|
581
796
|
def value
|
|
582
797
|
value_loc.slice
|
|
583
798
|
end
|
|
584
799
|
|
|
585
800
|
# Implement the hash pattern matching interface for MagicComment.
|
|
586
|
-
|
|
801
|
+
#
|
|
802
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
803
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
587
804
|
{ key_loc: key_loc, value_loc: value_loc }
|
|
588
805
|
end
|
|
589
806
|
|
|
590
807
|
# Returns a string representation of this magic comment.
|
|
591
|
-
|
|
808
|
+
#
|
|
809
|
+
#: () -> String
|
|
810
|
+
def inspect # :nodoc:
|
|
592
811
|
"#<Prism::MagicComment @key=#{key.inspect} @value=#{value.inspect}>"
|
|
593
812
|
end
|
|
594
813
|
end
|
|
@@ -597,18 +816,20 @@ module Prism
|
|
|
597
816
|
class ParseError
|
|
598
817
|
# The type of error. This is an _internal_ symbol that is used for
|
|
599
818
|
# communicating with translation layers. It is not meant to be public API.
|
|
600
|
-
attr_reader :type
|
|
819
|
+
attr_reader :type #: Symbol
|
|
601
820
|
|
|
602
821
|
# The message associated with this error.
|
|
603
|
-
attr_reader :message
|
|
822
|
+
attr_reader :message #: String
|
|
604
823
|
|
|
605
824
|
# A Location object representing the location of this error in the source.
|
|
606
|
-
attr_reader :location
|
|
825
|
+
attr_reader :location #: Location
|
|
607
826
|
|
|
608
827
|
# The level of this error.
|
|
609
|
-
attr_reader :level
|
|
828
|
+
attr_reader :level #: Symbol
|
|
610
829
|
|
|
611
830
|
# Create a new error object with the given message and location.
|
|
831
|
+
#
|
|
832
|
+
#: (Symbol type, String message, Location location, Symbol level) -> void
|
|
612
833
|
def initialize(type, message, location, level)
|
|
613
834
|
@type = type
|
|
614
835
|
@message = message
|
|
@@ -617,12 +838,16 @@ module Prism
|
|
|
617
838
|
end
|
|
618
839
|
|
|
619
840
|
# Implement the hash pattern matching interface for ParseError.
|
|
620
|
-
|
|
841
|
+
#
|
|
842
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
843
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
621
844
|
{ type: type, message: message, location: location, level: level }
|
|
622
845
|
end
|
|
623
846
|
|
|
624
847
|
# Returns a string representation of this error.
|
|
625
|
-
|
|
848
|
+
#
|
|
849
|
+
#: () -> String
|
|
850
|
+
def inspect # :nodoc:
|
|
626
851
|
"#<Prism::ParseError @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
|
|
627
852
|
end
|
|
628
853
|
end
|
|
@@ -631,18 +856,20 @@ module Prism
|
|
|
631
856
|
class ParseWarning
|
|
632
857
|
# The type of warning. This is an _internal_ symbol that is used for
|
|
633
858
|
# communicating with translation layers. It is not meant to be public API.
|
|
634
|
-
attr_reader :type
|
|
859
|
+
attr_reader :type #: Symbol
|
|
635
860
|
|
|
636
861
|
# The message associated with this warning.
|
|
637
|
-
attr_reader :message
|
|
862
|
+
attr_reader :message #: String
|
|
638
863
|
|
|
639
864
|
# A Location object representing the location of this warning in the source.
|
|
640
|
-
attr_reader :location
|
|
865
|
+
attr_reader :location #: Location
|
|
641
866
|
|
|
642
867
|
# The level of this warning.
|
|
643
|
-
attr_reader :level
|
|
868
|
+
attr_reader :level #: Symbol
|
|
644
869
|
|
|
645
870
|
# Create a new warning object with the given message and location.
|
|
871
|
+
#
|
|
872
|
+
#: (Symbol type, String message, Location location, Symbol level) -> void
|
|
646
873
|
def initialize(type, message, location, level)
|
|
647
874
|
@type = type
|
|
648
875
|
@message = message
|
|
@@ -651,73 +878,118 @@ module Prism
|
|
|
651
878
|
end
|
|
652
879
|
|
|
653
880
|
# Implement the hash pattern matching interface for ParseWarning.
|
|
654
|
-
|
|
881
|
+
#
|
|
882
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
883
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
655
884
|
{ type: type, message: message, location: location, level: level }
|
|
656
885
|
end
|
|
657
886
|
|
|
658
887
|
# Returns a string representation of this warning.
|
|
659
|
-
|
|
888
|
+
#
|
|
889
|
+
#: () -> String
|
|
890
|
+
def inspect # :nodoc:
|
|
660
891
|
"#<Prism::ParseWarning @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
|
|
661
892
|
end
|
|
662
893
|
end
|
|
663
894
|
|
|
664
|
-
# This represents the result of a call to
|
|
665
|
-
# the requested structure, any comments that were encounters,
|
|
666
|
-
# that were encountered.
|
|
895
|
+
# This represents the result of a call to Prism.parse or Prism.parse_file.
|
|
896
|
+
# It contains the requested structure, any comments that were encounters,
|
|
897
|
+
# and any errors that were encountered.
|
|
667
898
|
class Result
|
|
668
|
-
# The list of comments that were encountered during parsing.
|
|
669
|
-
attr_reader :comments
|
|
670
|
-
|
|
671
899
|
# The list of magic comments that were encountered during parsing.
|
|
672
|
-
attr_reader :magic_comments
|
|
900
|
+
attr_reader :magic_comments #: Array[MagicComment]
|
|
673
901
|
|
|
674
902
|
# An optional location that represents the location of the __END__ marker
|
|
675
903
|
# and the rest of the content of the file. This content is loaded into the
|
|
676
904
|
# DATA constant when the file being parsed is the main file being executed.
|
|
677
|
-
attr_reader :data_loc
|
|
905
|
+
attr_reader :data_loc #: Location?
|
|
678
906
|
|
|
679
907
|
# The list of errors that were generated during parsing.
|
|
680
|
-
attr_reader :errors
|
|
908
|
+
attr_reader :errors #: Array[ParseError]
|
|
681
909
|
|
|
682
910
|
# The list of warnings that were generated during parsing.
|
|
683
|
-
attr_reader :warnings
|
|
911
|
+
attr_reader :warnings #: Array[ParseWarning]
|
|
684
912
|
|
|
685
913
|
# A Source instance that represents the source code that was parsed.
|
|
686
|
-
attr_reader :source
|
|
914
|
+
attr_reader :source #: Source
|
|
687
915
|
|
|
688
916
|
# Create a new result object with the given values.
|
|
689
|
-
|
|
690
|
-
|
|
917
|
+
#
|
|
918
|
+
#: (Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void
|
|
919
|
+
def initialize(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
691
920
|
@magic_comments = magic_comments
|
|
692
921
|
@data_loc = data_loc
|
|
693
922
|
@errors = errors
|
|
694
923
|
@warnings = warnings
|
|
924
|
+
@continuable = continuable
|
|
695
925
|
@source = source
|
|
696
926
|
end
|
|
697
927
|
|
|
928
|
+
# The list of comments that were encountered during parsing.
|
|
929
|
+
#
|
|
930
|
+
#: () -> Array[Comment]
|
|
931
|
+
def comments
|
|
932
|
+
source.comments
|
|
933
|
+
end
|
|
934
|
+
|
|
698
935
|
# Implement the hash pattern matching interface for Result.
|
|
699
|
-
|
|
936
|
+
#
|
|
937
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
938
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
700
939
|
{ comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings }
|
|
701
940
|
end
|
|
702
941
|
|
|
703
942
|
# Returns the encoding of the source code that was parsed.
|
|
943
|
+
#
|
|
944
|
+
#: () -> Encoding
|
|
704
945
|
def encoding
|
|
705
946
|
source.encoding
|
|
706
947
|
end
|
|
707
948
|
|
|
708
949
|
# Returns true if there were no errors during parsing and false if there
|
|
709
950
|
# were.
|
|
951
|
+
#
|
|
952
|
+
#: () -> bool
|
|
710
953
|
def success?
|
|
711
954
|
errors.empty?
|
|
712
955
|
end
|
|
713
956
|
|
|
714
957
|
# Returns true if there were errors during parsing and false if there were
|
|
715
958
|
# not.
|
|
959
|
+
#
|
|
960
|
+
#: () -> bool
|
|
716
961
|
def failure?
|
|
717
962
|
!success?
|
|
718
963
|
end
|
|
719
964
|
|
|
965
|
+
# Returns true if the parsed source is an incomplete expression that could
|
|
966
|
+
# become valid with additional input. This is useful for REPL contexts (such
|
|
967
|
+
# as IRB) where the user may be entering a multi-line expression one line at
|
|
968
|
+
# a time and the implementation needs to determine whether to wait for more
|
|
969
|
+
# input or to evaluate what has been entered so far.
|
|
970
|
+
#
|
|
971
|
+
# Concretely, this returns true when every error present is caused by the
|
|
972
|
+
# parser reaching the end of the input before a construct was closed (e.g.
|
|
973
|
+
# an unclosed string, array, block, or keyword), and returns false when any
|
|
974
|
+
# error is caused by a token that makes the input structurally invalid
|
|
975
|
+
# regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no
|
|
976
|
+
# matching opener).
|
|
977
|
+
#
|
|
978
|
+
# Examples:
|
|
979
|
+
#
|
|
980
|
+
# Prism.parse("1 + [").continuable? #=> true (unclosed array)
|
|
981
|
+
# Prism.parse("1 + ]").continuable? #=> false (stray ])
|
|
982
|
+
# Prism.parse("tap do").continuable? #=> true (unclosed block)
|
|
983
|
+
# Prism.parse("end.tap do").continuable? #=> false (stray end)
|
|
984
|
+
#
|
|
985
|
+
#: () -> bool
|
|
986
|
+
def continuable?
|
|
987
|
+
@continuable
|
|
988
|
+
end
|
|
989
|
+
|
|
720
990
|
# Create a code units cache for the given encoding.
|
|
991
|
+
#
|
|
992
|
+
#: (Encoding encoding) -> _CodeUnitsCache
|
|
721
993
|
def code_units_cache(encoding)
|
|
722
994
|
source.code_units_cache(encoding)
|
|
723
995
|
end
|
|
@@ -725,41 +997,42 @@ module Prism
|
|
|
725
997
|
|
|
726
998
|
# This is a result specific to the `parse` and `parse_file` methods.
|
|
727
999
|
class ParseResult < Result
|
|
728
|
-
autoload :Comments, "prism/parse_result/comments"
|
|
729
1000
|
autoload :Errors, "prism/parse_result/errors"
|
|
730
1001
|
autoload :Newlines, "prism/parse_result/newlines"
|
|
731
1002
|
|
|
732
|
-
private_constant :Comments
|
|
733
1003
|
private_constant :Errors
|
|
734
1004
|
private_constant :Newlines
|
|
735
1005
|
|
|
736
1006
|
# The syntax tree that was parsed from the source code.
|
|
737
|
-
attr_reader :value
|
|
1007
|
+
attr_reader :value #: ProgramNode
|
|
738
1008
|
|
|
739
1009
|
# Create a new parse result object with the given values.
|
|
740
|
-
|
|
1010
|
+
#
|
|
1011
|
+
#: (ProgramNode value, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void
|
|
1012
|
+
def initialize(value, magic_comments, data_loc, errors, warnings, continuable, source)
|
|
741
1013
|
@value = value
|
|
742
|
-
super(
|
|
1014
|
+
super(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
743
1015
|
end
|
|
744
1016
|
|
|
745
1017
|
# Implement the hash pattern matching interface for ParseResult.
|
|
746
|
-
|
|
1018
|
+
#
|
|
1019
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1020
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
747
1021
|
super.merge!(value: value)
|
|
748
1022
|
end
|
|
749
1023
|
|
|
750
|
-
# Attach the list of comments to their respective locations in the tree.
|
|
751
|
-
def attach_comments!
|
|
752
|
-
Comments.new(self).attach! # steep:ignore
|
|
753
|
-
end
|
|
754
|
-
|
|
755
1024
|
# Walk the tree and mark nodes that are on a new line, loosely emulating
|
|
756
1025
|
# the behavior of CRuby's `:line` tracepoint event.
|
|
1026
|
+
#
|
|
1027
|
+
#: () -> void
|
|
757
1028
|
def mark_newlines!
|
|
758
1029
|
value.accept(Newlines.new(source.offsets.size)) # steep:ignore
|
|
759
1030
|
end
|
|
760
1031
|
|
|
761
1032
|
# Returns a string representation of the syntax tree with the errors
|
|
762
1033
|
# displayed inline.
|
|
1034
|
+
#
|
|
1035
|
+
#: () -> String
|
|
763
1036
|
def errors_format
|
|
764
1037
|
Errors.new(self).format
|
|
765
1038
|
end
|
|
@@ -768,16 +1041,20 @@ module Prism
|
|
|
768
1041
|
# This is a result specific to the `lex` and `lex_file` methods.
|
|
769
1042
|
class LexResult < Result
|
|
770
1043
|
# The list of tokens that were parsed from the source code.
|
|
771
|
-
attr_reader :value
|
|
1044
|
+
attr_reader :value #: Array[Token]
|
|
772
1045
|
|
|
773
1046
|
# Create a new lex result object with the given values.
|
|
774
|
-
|
|
1047
|
+
#
|
|
1048
|
+
#: (Array[Token] value, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void
|
|
1049
|
+
def initialize(value, magic_comments, data_loc, errors, warnings, continuable, source)
|
|
775
1050
|
@value = value
|
|
776
|
-
super(
|
|
1051
|
+
super(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
777
1052
|
end
|
|
778
1053
|
|
|
779
1054
|
# Implement the hash pattern matching interface for LexResult.
|
|
780
|
-
|
|
1055
|
+
#
|
|
1056
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1057
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
781
1058
|
super.merge!(value: value)
|
|
782
1059
|
end
|
|
783
1060
|
end
|
|
@@ -786,16 +1063,20 @@ module Prism
|
|
|
786
1063
|
class ParseLexResult < Result
|
|
787
1064
|
# A tuple of the syntax tree and the list of tokens that were parsed from
|
|
788
1065
|
# the source code.
|
|
789
|
-
attr_reader :value
|
|
1066
|
+
attr_reader :value #: [ProgramNode, Array[Token]]
|
|
790
1067
|
|
|
791
1068
|
# Create a new parse lex result object with the given values.
|
|
792
|
-
|
|
1069
|
+
#
|
|
1070
|
+
#: ([ProgramNode, Array[Token]] value, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void
|
|
1071
|
+
def initialize(value, magic_comments, data_loc, errors, warnings, continuable, source)
|
|
793
1072
|
@value = value
|
|
794
|
-
super(
|
|
1073
|
+
super(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
795
1074
|
end
|
|
796
1075
|
|
|
797
1076
|
# Implement the hash pattern matching interface for ParseLexResult.
|
|
798
|
-
|
|
1077
|
+
#
|
|
1078
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1079
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
799
1080
|
super.merge!(value: value)
|
|
800
1081
|
end
|
|
801
1082
|
end
|
|
@@ -803,29 +1084,38 @@ module Prism
|
|
|
803
1084
|
# This represents a token from the Ruby source.
|
|
804
1085
|
class Token
|
|
805
1086
|
# The Source object that represents the source this token came from.
|
|
806
|
-
attr_reader :source
|
|
1087
|
+
attr_reader :source #: Source
|
|
807
1088
|
private :source
|
|
808
1089
|
|
|
809
1090
|
# The type of token that this token is.
|
|
810
|
-
attr_reader :type
|
|
1091
|
+
attr_reader :type #: Symbol
|
|
811
1092
|
|
|
812
1093
|
# A byteslice of the source that this token represents.
|
|
813
|
-
attr_reader :value
|
|
1094
|
+
attr_reader :value #: String
|
|
1095
|
+
|
|
1096
|
+
# @rbs @location: Location | Integer
|
|
814
1097
|
|
|
815
1098
|
# Create a new token object with the given type, value, and location.
|
|
816
|
-
|
|
1099
|
+
#
|
|
1100
|
+
#: (Source source, Symbol type, String value, Location | Integer location, Integer state) -> void
|
|
1101
|
+
def initialize(source, type, value, location, state)
|
|
817
1102
|
@source = source
|
|
818
1103
|
@type = type
|
|
819
1104
|
@value = value
|
|
820
1105
|
@location = location
|
|
1106
|
+
@state = state
|
|
821
1107
|
end
|
|
822
1108
|
|
|
823
1109
|
# Implement the hash pattern matching interface for Token.
|
|
824
|
-
|
|
1110
|
+
#
|
|
1111
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1112
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
825
1113
|
{ type: type, value: value, location: location }
|
|
826
1114
|
end
|
|
827
1115
|
|
|
828
1116
|
# A Location object representing the location of this token in the source.
|
|
1117
|
+
#
|
|
1118
|
+
#: () -> Location
|
|
829
1119
|
def location
|
|
830
1120
|
location = @location
|
|
831
1121
|
return location if location.is_a?(Location)
|
|
@@ -833,7 +1123,9 @@ module Prism
|
|
|
833
1123
|
end
|
|
834
1124
|
|
|
835
1125
|
# Implement the pretty print interface for Token.
|
|
836
|
-
|
|
1126
|
+
#
|
|
1127
|
+
#: (PP q) -> void
|
|
1128
|
+
def pretty_print(q) # :nodoc:
|
|
837
1129
|
q.group do
|
|
838
1130
|
q.text(type.to_s)
|
|
839
1131
|
self.location.pretty_print(q)
|
|
@@ -848,6 +1140,8 @@ module Prism
|
|
|
848
1140
|
end
|
|
849
1141
|
|
|
850
1142
|
# Returns true if the given other token is equal to this token.
|
|
1143
|
+
#
|
|
1144
|
+
#: (untyped other) -> bool
|
|
851
1145
|
def ==(other)
|
|
852
1146
|
Token === other &&
|
|
853
1147
|
other.type == type &&
|
|
@@ -855,17 +1149,42 @@ module Prism
|
|
|
855
1149
|
end
|
|
856
1150
|
|
|
857
1151
|
# Returns a string representation of this token.
|
|
858
|
-
|
|
1152
|
+
#
|
|
1153
|
+
#: () -> String
|
|
1154
|
+
def inspect # :nodoc:
|
|
859
1155
|
location
|
|
860
1156
|
super
|
|
861
1157
|
end
|
|
862
1158
|
|
|
863
1159
|
# Freeze this object and the objects it contains.
|
|
1160
|
+
#
|
|
1161
|
+
#: () -> void
|
|
864
1162
|
def deep_freeze
|
|
865
1163
|
value.freeze
|
|
866
1164
|
location.freeze
|
|
867
1165
|
freeze
|
|
868
1166
|
end
|
|
1167
|
+
|
|
1168
|
+
# For internal use only.
|
|
1169
|
+
#: () -> Integer
|
|
1170
|
+
def _ripper_state # :nodoc:
|
|
1171
|
+
@state
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
# Backwards compatibility for Prism.lex/Prism.lex_file/Prism.parse_lex
|
|
1175
|
+
# when they returned a 2-element array.
|
|
1176
|
+
|
|
1177
|
+
#: (Integer index) -> Token | Integer
|
|
1178
|
+
def [](index) # :nodoc:
|
|
1179
|
+
return self if index == 0
|
|
1180
|
+
return @state if index == 1
|
|
1181
|
+
raise ArgumentError, "Invalid index #{index}"
|
|
1182
|
+
end
|
|
1183
|
+
|
|
1184
|
+
#: () -> Token
|
|
1185
|
+
def first # :nodoc:
|
|
1186
|
+
self
|
|
1187
|
+
end
|
|
869
1188
|
end
|
|
870
1189
|
|
|
871
1190
|
# This object is passed to the various Prism.* methods that accept the
|
|
@@ -875,14 +1194,16 @@ module Prism
|
|
|
875
1194
|
class Scope
|
|
876
1195
|
# The list of local variables that are defined in this scope. This should be
|
|
877
1196
|
# defined as an array of symbols.
|
|
878
|
-
attr_reader :locals
|
|
1197
|
+
attr_reader :locals #: Array[Symbol]
|
|
879
1198
|
|
|
880
1199
|
# The list of local variables that are forwarded to the next scope. This
|
|
881
1200
|
# should by defined as an array of symbols containing the specific values of
|
|
882
1201
|
# :*, :**, :&, or :"...".
|
|
883
|
-
attr_reader :forwarding
|
|
1202
|
+
attr_reader :forwarding #: Array[Symbol]
|
|
884
1203
|
|
|
885
1204
|
# Create a new scope object with the given locals and forwarding.
|
|
1205
|
+
#
|
|
1206
|
+
#: (Array[Symbol] locals, Array[Symbol] forwarding) -> void
|
|
886
1207
|
def initialize(locals, forwarding)
|
|
887
1208
|
@locals = locals
|
|
888
1209
|
@forwarding = forwarding
|
|
@@ -892,6 +1213,8 @@ module Prism
|
|
|
892
1213
|
# Create a new scope with the given locals and forwarding options that is
|
|
893
1214
|
# suitable for passing into one of the Prism.* methods that accepts the
|
|
894
1215
|
# `scopes` option.
|
|
1216
|
+
#
|
|
1217
|
+
#: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope
|
|
895
1218
|
def self.scope(locals: [], forwarding: [])
|
|
896
1219
|
Scope.new(locals, forwarding)
|
|
897
1220
|
end
|