prism 1.9.0 → 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 +84 -0
- data/Makefile +41 -12
- data/README.md +35 -97
- data/config.yml +174 -161
- 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/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 +2727 -610
- 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 -403
- 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 +12 -3
- 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 +254 -212
- data/lib/prism/mutation_compiler.rb +313 -305
- data/lib/prism/node.rb +20268 -7030
- 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 +453 -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 +3443 -535
- 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/lexer.rb +8 -10
- data/lib/prism/translation/ripper/sexp.rb +2 -10
- data/lib/prism/translation/ripper/shim.rb +2 -0
- data/lib/prism/translation/ripper.rb +967 -209
- 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 -9
- data/prism.gemspec +122 -60
- 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 +97 -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 +8030 -6970
- 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 +122 -61
- 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/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 -8750
- 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 -63
- 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 -4042
- 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 -197
- 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 -272
- 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,57 +51,113 @@ 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
|
|
|
79
158
|
# Converts the line number and column in bytes to a byte offset.
|
|
159
|
+
#
|
|
160
|
+
#: (Integer line, Integer column) -> Integer
|
|
80
161
|
def byte_offset(line, column)
|
|
81
162
|
normal = line - @start_line
|
|
82
163
|
raise IndexError if normal < 0
|
|
@@ -87,33 +168,45 @@ module Prism
|
|
|
87
168
|
|
|
88
169
|
# Binary search through the offsets to find the line number for the given
|
|
89
170
|
# byte offset.
|
|
171
|
+
#
|
|
172
|
+
#: (Integer byte_offset) -> Integer
|
|
90
173
|
def line(byte_offset)
|
|
91
174
|
start_line + find_line(byte_offset)
|
|
92
175
|
end
|
|
93
176
|
|
|
94
177
|
# Return the byte offset of the start of the line corresponding to the given
|
|
95
178
|
# byte offset.
|
|
179
|
+
#
|
|
180
|
+
#: (Integer byte_offset) -> Integer
|
|
96
181
|
def line_start(byte_offset)
|
|
97
182
|
offsets[find_line(byte_offset)]
|
|
98
183
|
end
|
|
99
184
|
|
|
100
185
|
# Returns the byte offset of the end of the line corresponding to the given
|
|
101
186
|
# byte offset.
|
|
187
|
+
#
|
|
188
|
+
#: (Integer byte_offset) -> Integer
|
|
102
189
|
def line_end(byte_offset)
|
|
103
190
|
offsets[find_line(byte_offset) + 1] || source.bytesize
|
|
104
191
|
end
|
|
105
192
|
|
|
106
|
-
# Return the column
|
|
193
|
+
# Return the column in bytes for the given byte offset.
|
|
194
|
+
#
|
|
195
|
+
#: (Integer byte_offset) -> Integer
|
|
107
196
|
def column(byte_offset)
|
|
108
197
|
byte_offset - line_start(byte_offset)
|
|
109
198
|
end
|
|
110
199
|
|
|
111
200
|
# Return the character offset for the given byte offset.
|
|
201
|
+
#
|
|
202
|
+
#: (Integer byte_offset) -> Integer
|
|
112
203
|
def character_offset(byte_offset)
|
|
113
204
|
(source.byteslice(0, byte_offset) or raise).length
|
|
114
205
|
end
|
|
115
206
|
|
|
116
|
-
# Return the column
|
|
207
|
+
# Return the column in characters for the given byte offset.
|
|
208
|
+
#
|
|
209
|
+
#: (Integer byte_offset) -> Integer
|
|
117
210
|
def character_column(byte_offset)
|
|
118
211
|
character_offset(byte_offset) - character_offset(line_start(byte_offset))
|
|
119
212
|
end
|
|
@@ -130,7 +223,11 @@ module Prism
|
|
|
130
223
|
# possible that the given byte offset will not occur on a character
|
|
131
224
|
# boundary. Second, it's possible that the source code will contain a
|
|
132
225
|
# character that has no equivalent in the given encoding.
|
|
226
|
+
#
|
|
227
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
133
228
|
def code_units_offset(byte_offset, encoding)
|
|
229
|
+
return byte_offset if encoding == Encoding::UTF_8
|
|
230
|
+
|
|
134
231
|
byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace)
|
|
135
232
|
|
|
136
233
|
if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE
|
|
@@ -142,28 +239,37 @@ module Prism
|
|
|
142
239
|
|
|
143
240
|
# Generate a cache that targets a specific encoding for calculating code
|
|
144
241
|
# unit offsets.
|
|
242
|
+
#
|
|
243
|
+
#: (Encoding encoding) -> CodeUnitsCache
|
|
145
244
|
def code_units_cache(encoding)
|
|
146
245
|
CodeUnitsCache.new(source, encoding)
|
|
147
246
|
end
|
|
148
247
|
|
|
149
|
-
# Returns the column
|
|
248
|
+
# Returns the column in code units for the given encoding for the
|
|
150
249
|
# given byte offset.
|
|
250
|
+
#
|
|
251
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
151
252
|
def code_units_column(byte_offset, encoding)
|
|
152
253
|
code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
|
|
153
254
|
end
|
|
154
255
|
|
|
155
256
|
# Freeze this object and the objects it contains.
|
|
257
|
+
#
|
|
258
|
+
#: () -> void
|
|
156
259
|
def deep_freeze
|
|
157
260
|
source.freeze
|
|
158
261
|
offsets.freeze
|
|
262
|
+
comments.freeze
|
|
263
|
+
comment_attachments.freeze
|
|
264
|
+
comment_ranges.freeze
|
|
159
265
|
freeze
|
|
160
266
|
end
|
|
161
267
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
# 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
|
|
165
269
|
# byte offset.
|
|
166
|
-
|
|
270
|
+
#
|
|
271
|
+
#: (Integer byte_offset) -> Integer
|
|
272
|
+
def find_line(byte_offset) # :nodoc:
|
|
167
273
|
index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length
|
|
168
274
|
index - 1
|
|
169
275
|
end
|
|
@@ -184,38 +290,69 @@ module Prism
|
|
|
184
290
|
# has not yet been implemented.
|
|
185
291
|
#
|
|
186
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
|
+
|
|
187
301
|
class UTF16Counter # :nodoc:
|
|
302
|
+
# @rbs @source: String
|
|
303
|
+
# @rbs @encoding: Encoding
|
|
304
|
+
|
|
305
|
+
#: (String source, Encoding encoding) -> void
|
|
188
306
|
def initialize(source, encoding)
|
|
189
307
|
@source = source
|
|
190
308
|
@encoding = encoding
|
|
191
309
|
end
|
|
192
310
|
|
|
311
|
+
#: (Integer byte_offset, Integer byte_length) -> Integer
|
|
193
312
|
def count(byte_offset, byte_length)
|
|
194
|
-
@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
|
|
195
314
|
end
|
|
196
315
|
end
|
|
197
316
|
|
|
198
|
-
|
|
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
|
|
199
325
|
def initialize(source, encoding)
|
|
200
326
|
@source = source
|
|
201
327
|
@encoding = encoding
|
|
202
328
|
end
|
|
203
329
|
|
|
330
|
+
#: (Integer byte_offset, Integer byte_length) -> Integer
|
|
204
331
|
def count(byte_offset, byte_length)
|
|
205
|
-
@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
|
|
206
333
|
end
|
|
207
334
|
end
|
|
208
335
|
|
|
209
|
-
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]
|
|
210
342
|
|
|
211
343
|
# Initialize a new cache with the given source and encoding.
|
|
344
|
+
#
|
|
345
|
+
#: (String source, Encoding encoding) -> void
|
|
212
346
|
def initialize(source, encoding)
|
|
213
347
|
@source = source
|
|
214
348
|
@counter =
|
|
215
|
-
|
|
349
|
+
case encoding
|
|
350
|
+
when Encoding::UTF_8
|
|
351
|
+
UTF8Counter.new
|
|
352
|
+
when Encoding::UTF_16LE, Encoding::UTF_16BE
|
|
216
353
|
UTF16Counter.new(source, encoding)
|
|
217
354
|
else
|
|
218
|
-
|
|
355
|
+
UTF32Counter.new(source, encoding)
|
|
219
356
|
end
|
|
220
357
|
|
|
221
358
|
@cache = {} #: Hash[Integer, Integer]
|
|
@@ -223,6 +360,8 @@ module Prism
|
|
|
223
360
|
end
|
|
224
361
|
|
|
225
362
|
# Retrieve the code units offset from the given byte offset.
|
|
363
|
+
#
|
|
364
|
+
#: (Integer byte_offset) -> Integer
|
|
226
365
|
def [](byte_offset)
|
|
227
366
|
@cache[byte_offset] ||=
|
|
228
367
|
if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil?
|
|
@@ -249,11 +388,15 @@ module Prism
|
|
|
249
388
|
# at that point we will treat everything as single-byte characters.
|
|
250
389
|
class ASCIISource < Source
|
|
251
390
|
# Return the character offset for the given byte offset.
|
|
391
|
+
#
|
|
392
|
+
#: (Integer byte_offset) -> Integer
|
|
252
393
|
def character_offset(byte_offset)
|
|
253
394
|
byte_offset
|
|
254
395
|
end
|
|
255
396
|
|
|
256
|
-
# Return the column
|
|
397
|
+
# Return the column in characters for the given byte offset.
|
|
398
|
+
#
|
|
399
|
+
#: (Integer byte_offset) -> Integer
|
|
257
400
|
def character_column(byte_offset)
|
|
258
401
|
byte_offset - line_start(byte_offset)
|
|
259
402
|
end
|
|
@@ -264,6 +407,8 @@ module Prism
|
|
|
264
407
|
# This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
|
|
265
408
|
# concept of code units that differs from the number of characters in other
|
|
266
409
|
# encodings, it is not captured here.
|
|
410
|
+
#
|
|
411
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
267
412
|
def code_units_offset(byte_offset, encoding)
|
|
268
413
|
byte_offset
|
|
269
414
|
end
|
|
@@ -271,6 +416,8 @@ module Prism
|
|
|
271
416
|
# Returns a cache that is the identity function in order to maintain the
|
|
272
417
|
# same interface. We can do this because code units are always equivalent to
|
|
273
418
|
# byte offsets for ASCII-only sources.
|
|
419
|
+
#
|
|
420
|
+
#: (Encoding encoding) -> _CodeUnitsCache
|
|
274
421
|
def code_units_cache(encoding)
|
|
275
422
|
->(byte_offset) { byte_offset }
|
|
276
423
|
end
|
|
@@ -278,6 +425,8 @@ module Prism
|
|
|
278
425
|
# Specialized version of `code_units_column` that does not depend on
|
|
279
426
|
# `code_units_offset`, which is a more expensive operation. This is
|
|
280
427
|
# essentially the same as `Prism::Source#column`.
|
|
428
|
+
#
|
|
429
|
+
#: (Integer byte_offset, Encoding encoding) -> Integer
|
|
281
430
|
def code_units_column(byte_offset, encoding)
|
|
282
431
|
byte_offset - line_start(byte_offset)
|
|
283
432
|
end
|
|
@@ -287,79 +436,57 @@ module Prism
|
|
|
287
436
|
class Location
|
|
288
437
|
# A Source object that is used to determine more information from the given
|
|
289
438
|
# offset and length.
|
|
290
|
-
attr_reader :source
|
|
439
|
+
attr_reader :source #: Source
|
|
291
440
|
protected :source
|
|
292
441
|
|
|
293
442
|
# The byte offset from the beginning of the source where this location
|
|
294
443
|
# starts.
|
|
295
|
-
attr_reader :start_offset
|
|
444
|
+
attr_reader :start_offset #: Integer
|
|
296
445
|
|
|
297
446
|
# The length of this location in bytes.
|
|
298
|
-
attr_reader :length
|
|
447
|
+
attr_reader :length #: Integer
|
|
299
448
|
|
|
300
449
|
# Create a new location object with the given source, start byte offset, and
|
|
301
450
|
# byte length.
|
|
451
|
+
#
|
|
452
|
+
#: (Source source, Integer start_offset, Integer length) -> void
|
|
302
453
|
def initialize(source, start_offset, length)
|
|
303
454
|
@source = source
|
|
304
455
|
@start_offset = start_offset
|
|
305
456
|
@length = length
|
|
306
|
-
|
|
307
|
-
# These are used to store comments that are associated with this location.
|
|
308
|
-
# They are initialized to `nil` to save on memory when there are no
|
|
309
|
-
# comments to be attached and/or the comment-related APIs are not used.
|
|
310
|
-
@leading_comments = nil
|
|
311
|
-
@trailing_comments = nil
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
# These are the comments that are associated with this location that exist
|
|
315
|
-
# before the start of this location.
|
|
316
|
-
def leading_comments
|
|
317
|
-
@leading_comments ||= []
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
# Attach a comment to the leading comments of this location.
|
|
321
|
-
def leading_comment(comment)
|
|
322
|
-
leading_comments << comment
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
# These are the comments that are associated with this location that exist
|
|
326
|
-
# after the end of this location.
|
|
327
|
-
def trailing_comments
|
|
328
|
-
@trailing_comments ||= []
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
# Attach a comment to the trailing comments of this location.
|
|
332
|
-
def trailing_comment(comment)
|
|
333
|
-
trailing_comments << comment
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
# Returns all comments that are associated with this location (both leading
|
|
337
|
-
# and trailing comments).
|
|
338
|
-
def comments
|
|
339
|
-
[*@leading_comments, *@trailing_comments]
|
|
340
457
|
end
|
|
341
458
|
|
|
342
459
|
# Create a new location object with the given options.
|
|
460
|
+
#
|
|
461
|
+
#: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location
|
|
343
462
|
def copy(source: self.source, start_offset: self.start_offset, length: self.length)
|
|
344
463
|
Location.new(source, start_offset, length)
|
|
345
464
|
end
|
|
346
465
|
|
|
347
466
|
# Returns a new location that is the result of chopping off the last byte.
|
|
467
|
+
#
|
|
468
|
+
#: () -> Location
|
|
348
469
|
def chop
|
|
349
470
|
copy(length: length == 0 ? length : length - 1)
|
|
350
471
|
end
|
|
351
472
|
|
|
352
473
|
# Returns a string representation of this location.
|
|
353
|
-
|
|
474
|
+
#
|
|
475
|
+
#: () -> String
|
|
476
|
+
def inspect # :nodoc:
|
|
354
477
|
"#<Prism::Location @start_offset=#{@start_offset} @length=#{@length} start_line=#{start_line}>"
|
|
355
478
|
end
|
|
356
479
|
|
|
357
480
|
# Returns all of the lines of the source code associated with this location.
|
|
481
|
+
#
|
|
482
|
+
#: () -> Array[String]
|
|
358
483
|
def source_lines
|
|
359
484
|
source.lines
|
|
360
485
|
end
|
|
361
486
|
|
|
362
487
|
# The source code that this location represents.
|
|
488
|
+
#
|
|
489
|
+
#: () -> String
|
|
363
490
|
def slice
|
|
364
491
|
source.slice(start_offset, length)
|
|
365
492
|
end
|
|
@@ -367,6 +494,8 @@ module Prism
|
|
|
367
494
|
# The source code that this location represents starting from the beginning
|
|
368
495
|
# of the line that this location starts on to the end of the line that this
|
|
369
496
|
# location ends on.
|
|
497
|
+
#
|
|
498
|
+
#: () -> String
|
|
370
499
|
def slice_lines
|
|
371
500
|
line_start = source.line_start(start_offset)
|
|
372
501
|
line_end = source.line_end(end_offset)
|
|
@@ -375,118 +504,160 @@ module Prism
|
|
|
375
504
|
|
|
376
505
|
# The character offset from the beginning of the source where this location
|
|
377
506
|
# starts.
|
|
507
|
+
#
|
|
508
|
+
#: () -> Integer
|
|
378
509
|
def start_character_offset
|
|
379
510
|
source.character_offset(start_offset)
|
|
380
511
|
end
|
|
381
512
|
|
|
382
513
|
# The offset from the start of the file in code units of the given encoding.
|
|
514
|
+
#
|
|
515
|
+
#: (Encoding encoding) -> Integer
|
|
383
516
|
def start_code_units_offset(encoding = Encoding::UTF_16LE)
|
|
384
517
|
source.code_units_offset(start_offset, encoding)
|
|
385
518
|
end
|
|
386
519
|
|
|
387
520
|
# The start offset from the start of the file in code units using the given
|
|
388
521
|
# cache to fetch or calculate the value.
|
|
522
|
+
#
|
|
523
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
389
524
|
def cached_start_code_units_offset(cache)
|
|
390
525
|
cache[start_offset]
|
|
391
526
|
end
|
|
392
527
|
|
|
393
528
|
# The byte offset from the beginning of the source where this location ends.
|
|
529
|
+
#
|
|
530
|
+
#: () -> Integer
|
|
394
531
|
def end_offset
|
|
395
532
|
start_offset + length
|
|
396
533
|
end
|
|
397
534
|
|
|
398
535
|
# The character offset from the beginning of the source where this location
|
|
399
536
|
# ends.
|
|
537
|
+
#
|
|
538
|
+
#: () -> Integer
|
|
400
539
|
def end_character_offset
|
|
401
540
|
source.character_offset(end_offset)
|
|
402
541
|
end
|
|
403
542
|
|
|
404
543
|
# The offset from the start of the file in code units of the given encoding.
|
|
544
|
+
#
|
|
545
|
+
#: (Encoding encoding) -> Integer
|
|
405
546
|
def end_code_units_offset(encoding = Encoding::UTF_16LE)
|
|
406
547
|
source.code_units_offset(end_offset, encoding)
|
|
407
548
|
end
|
|
408
549
|
|
|
409
550
|
# The end offset from the start of the file in code units using the given
|
|
410
551
|
# cache to fetch or calculate the value.
|
|
552
|
+
#
|
|
553
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
411
554
|
def cached_end_code_units_offset(cache)
|
|
412
555
|
cache[end_offset]
|
|
413
556
|
end
|
|
414
557
|
|
|
415
558
|
# The line number where this location starts.
|
|
559
|
+
#
|
|
560
|
+
#: () -> Integer
|
|
416
561
|
def start_line
|
|
417
562
|
source.line(start_offset)
|
|
418
563
|
end
|
|
419
564
|
|
|
420
565
|
# The content of the line where this location starts before this location.
|
|
566
|
+
#
|
|
567
|
+
#: () -> String
|
|
421
568
|
def start_line_slice
|
|
422
569
|
offset = source.line_start(start_offset)
|
|
423
570
|
source.slice(offset, start_offset - offset)
|
|
424
571
|
end
|
|
425
572
|
|
|
426
573
|
# The line number where this location ends.
|
|
574
|
+
#
|
|
575
|
+
#: () -> Integer
|
|
427
576
|
def end_line
|
|
428
577
|
source.line(end_offset)
|
|
429
578
|
end
|
|
430
579
|
|
|
431
|
-
# The column
|
|
580
|
+
# The column in bytes where this location starts from the start of
|
|
432
581
|
# the line.
|
|
582
|
+
#
|
|
583
|
+
#: () -> Integer
|
|
433
584
|
def start_column
|
|
434
585
|
source.column(start_offset)
|
|
435
586
|
end
|
|
436
587
|
|
|
437
|
-
# The column
|
|
588
|
+
# The column in characters where this location ends from the start of
|
|
438
589
|
# the line.
|
|
590
|
+
#
|
|
591
|
+
#: () -> Integer
|
|
439
592
|
def start_character_column
|
|
440
593
|
source.character_column(start_offset)
|
|
441
594
|
end
|
|
442
595
|
|
|
443
|
-
# The column
|
|
596
|
+
# The column in code units of the given encoding where this location
|
|
444
597
|
# starts from the start of the line.
|
|
598
|
+
#
|
|
599
|
+
#: (?Encoding encoding) -> Integer
|
|
445
600
|
def start_code_units_column(encoding = Encoding::UTF_16LE)
|
|
446
601
|
source.code_units_column(start_offset, encoding)
|
|
447
602
|
end
|
|
448
603
|
|
|
449
604
|
# The start column in code units using the given cache to fetch or calculate
|
|
450
605
|
# the value.
|
|
606
|
+
#
|
|
607
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
451
608
|
def cached_start_code_units_column(cache)
|
|
452
609
|
cache[start_offset] - cache[source.line_start(start_offset)]
|
|
453
610
|
end
|
|
454
611
|
|
|
455
|
-
# The column
|
|
612
|
+
# The column in bytes where this location ends from the start of the
|
|
456
613
|
# line.
|
|
614
|
+
#
|
|
615
|
+
#: () -> Integer
|
|
457
616
|
def end_column
|
|
458
617
|
source.column(end_offset)
|
|
459
618
|
end
|
|
460
619
|
|
|
461
|
-
# The column
|
|
620
|
+
# The column in characters where this location ends from the start of
|
|
462
621
|
# the line.
|
|
622
|
+
#
|
|
623
|
+
#: () -> Integer
|
|
463
624
|
def end_character_column
|
|
464
625
|
source.character_column(end_offset)
|
|
465
626
|
end
|
|
466
627
|
|
|
467
|
-
# The column
|
|
628
|
+
# The column in code units of the given encoding where this location
|
|
468
629
|
# ends from the start of the line.
|
|
630
|
+
#
|
|
631
|
+
#: (?Encoding encoding) -> Integer
|
|
469
632
|
def end_code_units_column(encoding = Encoding::UTF_16LE)
|
|
470
633
|
source.code_units_column(end_offset, encoding)
|
|
471
634
|
end
|
|
472
635
|
|
|
473
636
|
# The end column in code units using the given cache to fetch or calculate
|
|
474
637
|
# the value.
|
|
638
|
+
#
|
|
639
|
+
#: (_CodeUnitsCache cache) -> Integer
|
|
475
640
|
def cached_end_code_units_column(cache)
|
|
476
641
|
cache[end_offset] - cache[source.line_start(end_offset)]
|
|
477
642
|
end
|
|
478
643
|
|
|
479
644
|
# Implement the hash pattern matching interface for Location.
|
|
480
|
-
|
|
645
|
+
#
|
|
646
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
647
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
481
648
|
{ start_offset: start_offset, end_offset: end_offset }
|
|
482
649
|
end
|
|
483
650
|
|
|
484
651
|
# Implement the pretty print interface for Location.
|
|
485
|
-
|
|
652
|
+
#
|
|
653
|
+
#: (PP q) -> void
|
|
654
|
+
def pretty_print(q) # :nodoc:
|
|
486
655
|
q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})")
|
|
487
656
|
end
|
|
488
657
|
|
|
489
658
|
# Returns true if the given other location is equal to this location.
|
|
659
|
+
#
|
|
660
|
+
#: (untyped other) -> bool
|
|
490
661
|
def ==(other)
|
|
491
662
|
Location === other &&
|
|
492
663
|
other.start_offset == start_offset &&
|
|
@@ -496,6 +667,8 @@ module Prism
|
|
|
496
667
|
# Returns a new location that stretches from this location to the given
|
|
497
668
|
# other location. Raises an error if this location is not before the other
|
|
498
669
|
# location or if they don't share the same source.
|
|
670
|
+
#
|
|
671
|
+
#: (Location other) -> Location
|
|
499
672
|
def join(other)
|
|
500
673
|
raise "Incompatible sources" if source != other.source
|
|
501
674
|
raise "Incompatible locations" if start_offset > other.start_offset
|
|
@@ -506,6 +679,8 @@ module Prism
|
|
|
506
679
|
# Join this location with the first occurrence of the string in the source
|
|
507
680
|
# that occurs after this location on the same line, and return the new
|
|
508
681
|
# location. This will raise an error if the string does not exist.
|
|
682
|
+
#
|
|
683
|
+
#: (String string) -> Location
|
|
509
684
|
def adjoin(string)
|
|
510
685
|
line_suffix = source.slice(end_offset, source.line_end(end_offset) - end_offset)
|
|
511
686
|
|
|
@@ -519,23 +694,38 @@ module Prism
|
|
|
519
694
|
# This represents a comment that was encountered during parsing. It is the
|
|
520
695
|
# base class for all comment types.
|
|
521
696
|
class Comment
|
|
522
|
-
# The
|
|
523
|
-
attr_reader :location
|
|
697
|
+
# The Location of this comment in the source.
|
|
698
|
+
attr_reader :location #: Location
|
|
524
699
|
|
|
525
700
|
# Create a new comment object with the given location.
|
|
701
|
+
#
|
|
702
|
+
#: (Location location) -> void
|
|
526
703
|
def initialize(location)
|
|
527
704
|
@location = location
|
|
528
705
|
end
|
|
529
706
|
|
|
530
707
|
# Implement the hash pattern matching interface for Comment.
|
|
531
|
-
|
|
708
|
+
#
|
|
709
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
710
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
532
711
|
{ location: location }
|
|
533
712
|
end
|
|
534
713
|
|
|
535
714
|
# Returns the content of the comment by slicing it from the source code.
|
|
715
|
+
#
|
|
716
|
+
#: () -> String
|
|
536
717
|
def slice
|
|
537
718
|
location.slice
|
|
538
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
|
|
539
729
|
end
|
|
540
730
|
|
|
541
731
|
# InlineComment objects are the most common. They correspond to comments in
|
|
@@ -543,12 +733,18 @@ module Prism
|
|
|
543
733
|
class InlineComment < Comment
|
|
544
734
|
# Returns true if this comment happens on the same line as other code and
|
|
545
735
|
# false if the comment is by itself.
|
|
736
|
+
#
|
|
737
|
+
#: () -> bool
|
|
546
738
|
def trailing?
|
|
547
739
|
!location.start_line_slice.strip.empty?
|
|
740
|
+
rescue ArgumentError # invalid bytes, never whitespace only
|
|
741
|
+
false
|
|
548
742
|
end
|
|
549
743
|
|
|
550
744
|
# Returns a string representation of this comment.
|
|
551
|
-
|
|
745
|
+
#
|
|
746
|
+
#: () -> String
|
|
747
|
+
def inspect # :nodoc:
|
|
552
748
|
"#<Prism::InlineComment @location=#{location.inspect}>"
|
|
553
749
|
end
|
|
554
750
|
end
|
|
@@ -556,13 +752,17 @@ module Prism
|
|
|
556
752
|
# EmbDocComment objects correspond to comments that are surrounded by =begin
|
|
557
753
|
# and =end.
|
|
558
754
|
class EmbDocComment < Comment
|
|
559
|
-
# This can only be true for inline comments.
|
|
755
|
+
# Returns false. This can only be true for inline comments.
|
|
756
|
+
#
|
|
757
|
+
#: () -> bool
|
|
560
758
|
def trailing?
|
|
561
759
|
false
|
|
562
760
|
end
|
|
563
761
|
|
|
564
762
|
# Returns a string representation of this comment.
|
|
565
|
-
|
|
763
|
+
#
|
|
764
|
+
#: () -> String
|
|
765
|
+
def inspect # :nodoc:
|
|
566
766
|
"#<Prism::EmbDocComment @location=#{location.inspect}>"
|
|
567
767
|
end
|
|
568
768
|
end
|
|
@@ -570,34 +770,44 @@ module Prism
|
|
|
570
770
|
# This represents a magic comment that was encountered during parsing.
|
|
571
771
|
class MagicComment
|
|
572
772
|
# A Location object representing the location of the key in the source.
|
|
573
|
-
attr_reader :key_loc
|
|
773
|
+
attr_reader :key_loc #: Location
|
|
574
774
|
|
|
575
775
|
# A Location object representing the location of the value in the source.
|
|
576
|
-
attr_reader :value_loc
|
|
776
|
+
attr_reader :value_loc #: Location
|
|
577
777
|
|
|
578
778
|
# Create a new magic comment object with the given key and value locations.
|
|
779
|
+
#
|
|
780
|
+
#: (Location key_loc, Location value_loc) -> void
|
|
579
781
|
def initialize(key_loc, value_loc)
|
|
580
782
|
@key_loc = key_loc
|
|
581
783
|
@value_loc = value_loc
|
|
582
784
|
end
|
|
583
785
|
|
|
584
786
|
# Returns the key of the magic comment by slicing it from the source code.
|
|
787
|
+
#
|
|
788
|
+
#: () -> String
|
|
585
789
|
def key
|
|
586
790
|
key_loc.slice
|
|
587
791
|
end
|
|
588
792
|
|
|
589
793
|
# Returns the value of the magic comment by slicing it from the source code.
|
|
794
|
+
#
|
|
795
|
+
#: () -> String
|
|
590
796
|
def value
|
|
591
797
|
value_loc.slice
|
|
592
798
|
end
|
|
593
799
|
|
|
594
800
|
# Implement the hash pattern matching interface for MagicComment.
|
|
595
|
-
|
|
801
|
+
#
|
|
802
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
803
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
596
804
|
{ key_loc: key_loc, value_loc: value_loc }
|
|
597
805
|
end
|
|
598
806
|
|
|
599
807
|
# Returns a string representation of this magic comment.
|
|
600
|
-
|
|
808
|
+
#
|
|
809
|
+
#: () -> String
|
|
810
|
+
def inspect # :nodoc:
|
|
601
811
|
"#<Prism::MagicComment @key=#{key.inspect} @value=#{value.inspect}>"
|
|
602
812
|
end
|
|
603
813
|
end
|
|
@@ -606,18 +816,20 @@ module Prism
|
|
|
606
816
|
class ParseError
|
|
607
817
|
# The type of error. This is an _internal_ symbol that is used for
|
|
608
818
|
# communicating with translation layers. It is not meant to be public API.
|
|
609
|
-
attr_reader :type
|
|
819
|
+
attr_reader :type #: Symbol
|
|
610
820
|
|
|
611
821
|
# The message associated with this error.
|
|
612
|
-
attr_reader :message
|
|
822
|
+
attr_reader :message #: String
|
|
613
823
|
|
|
614
824
|
# A Location object representing the location of this error in the source.
|
|
615
|
-
attr_reader :location
|
|
825
|
+
attr_reader :location #: Location
|
|
616
826
|
|
|
617
827
|
# The level of this error.
|
|
618
|
-
attr_reader :level
|
|
828
|
+
attr_reader :level #: Symbol
|
|
619
829
|
|
|
620
830
|
# Create a new error object with the given message and location.
|
|
831
|
+
#
|
|
832
|
+
#: (Symbol type, String message, Location location, Symbol level) -> void
|
|
621
833
|
def initialize(type, message, location, level)
|
|
622
834
|
@type = type
|
|
623
835
|
@message = message
|
|
@@ -626,12 +838,16 @@ module Prism
|
|
|
626
838
|
end
|
|
627
839
|
|
|
628
840
|
# Implement the hash pattern matching interface for ParseError.
|
|
629
|
-
|
|
841
|
+
#
|
|
842
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
843
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
630
844
|
{ type: type, message: message, location: location, level: level }
|
|
631
845
|
end
|
|
632
846
|
|
|
633
847
|
# Returns a string representation of this error.
|
|
634
|
-
|
|
848
|
+
#
|
|
849
|
+
#: () -> String
|
|
850
|
+
def inspect # :nodoc:
|
|
635
851
|
"#<Prism::ParseError @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
|
|
636
852
|
end
|
|
637
853
|
end
|
|
@@ -640,18 +856,20 @@ module Prism
|
|
|
640
856
|
class ParseWarning
|
|
641
857
|
# The type of warning. This is an _internal_ symbol that is used for
|
|
642
858
|
# communicating with translation layers. It is not meant to be public API.
|
|
643
|
-
attr_reader :type
|
|
859
|
+
attr_reader :type #: Symbol
|
|
644
860
|
|
|
645
861
|
# The message associated with this warning.
|
|
646
|
-
attr_reader :message
|
|
862
|
+
attr_reader :message #: String
|
|
647
863
|
|
|
648
864
|
# A Location object representing the location of this warning in the source.
|
|
649
|
-
attr_reader :location
|
|
865
|
+
attr_reader :location #: Location
|
|
650
866
|
|
|
651
867
|
# The level of this warning.
|
|
652
|
-
attr_reader :level
|
|
868
|
+
attr_reader :level #: Symbol
|
|
653
869
|
|
|
654
870
|
# Create a new warning object with the given message and location.
|
|
871
|
+
#
|
|
872
|
+
#: (Symbol type, String message, Location location, Symbol level) -> void
|
|
655
873
|
def initialize(type, message, location, level)
|
|
656
874
|
@type = type
|
|
657
875
|
@message = message
|
|
@@ -660,73 +878,118 @@ module Prism
|
|
|
660
878
|
end
|
|
661
879
|
|
|
662
880
|
# Implement the hash pattern matching interface for ParseWarning.
|
|
663
|
-
|
|
881
|
+
#
|
|
882
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
883
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
664
884
|
{ type: type, message: message, location: location, level: level }
|
|
665
885
|
end
|
|
666
886
|
|
|
667
887
|
# Returns a string representation of this warning.
|
|
668
|
-
|
|
888
|
+
#
|
|
889
|
+
#: () -> String
|
|
890
|
+
def inspect # :nodoc:
|
|
669
891
|
"#<Prism::ParseWarning @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
|
|
670
892
|
end
|
|
671
893
|
end
|
|
672
894
|
|
|
673
|
-
# This represents the result of a call to
|
|
674
|
-
# the requested structure, any comments that were encounters,
|
|
675
|
-
# 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.
|
|
676
898
|
class Result
|
|
677
|
-
# The list of comments that were encountered during parsing.
|
|
678
|
-
attr_reader :comments
|
|
679
|
-
|
|
680
899
|
# The list of magic comments that were encountered during parsing.
|
|
681
|
-
attr_reader :magic_comments
|
|
900
|
+
attr_reader :magic_comments #: Array[MagicComment]
|
|
682
901
|
|
|
683
902
|
# An optional location that represents the location of the __END__ marker
|
|
684
903
|
# and the rest of the content of the file. This content is loaded into the
|
|
685
904
|
# DATA constant when the file being parsed is the main file being executed.
|
|
686
|
-
attr_reader :data_loc
|
|
905
|
+
attr_reader :data_loc #: Location?
|
|
687
906
|
|
|
688
907
|
# The list of errors that were generated during parsing.
|
|
689
|
-
attr_reader :errors
|
|
908
|
+
attr_reader :errors #: Array[ParseError]
|
|
690
909
|
|
|
691
910
|
# The list of warnings that were generated during parsing.
|
|
692
|
-
attr_reader :warnings
|
|
911
|
+
attr_reader :warnings #: Array[ParseWarning]
|
|
693
912
|
|
|
694
913
|
# A Source instance that represents the source code that was parsed.
|
|
695
|
-
attr_reader :source
|
|
914
|
+
attr_reader :source #: Source
|
|
696
915
|
|
|
697
916
|
# Create a new result object with the given values.
|
|
698
|
-
|
|
699
|
-
|
|
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)
|
|
700
920
|
@magic_comments = magic_comments
|
|
701
921
|
@data_loc = data_loc
|
|
702
922
|
@errors = errors
|
|
703
923
|
@warnings = warnings
|
|
924
|
+
@continuable = continuable
|
|
704
925
|
@source = source
|
|
705
926
|
end
|
|
706
927
|
|
|
928
|
+
# The list of comments that were encountered during parsing.
|
|
929
|
+
#
|
|
930
|
+
#: () -> Array[Comment]
|
|
931
|
+
def comments
|
|
932
|
+
source.comments
|
|
933
|
+
end
|
|
934
|
+
|
|
707
935
|
# Implement the hash pattern matching interface for Result.
|
|
708
|
-
|
|
936
|
+
#
|
|
937
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
938
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
709
939
|
{ comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings }
|
|
710
940
|
end
|
|
711
941
|
|
|
712
942
|
# Returns the encoding of the source code that was parsed.
|
|
943
|
+
#
|
|
944
|
+
#: () -> Encoding
|
|
713
945
|
def encoding
|
|
714
946
|
source.encoding
|
|
715
947
|
end
|
|
716
948
|
|
|
717
949
|
# Returns true if there were no errors during parsing and false if there
|
|
718
950
|
# were.
|
|
951
|
+
#
|
|
952
|
+
#: () -> bool
|
|
719
953
|
def success?
|
|
720
954
|
errors.empty?
|
|
721
955
|
end
|
|
722
956
|
|
|
723
957
|
# Returns true if there were errors during parsing and false if there were
|
|
724
958
|
# not.
|
|
959
|
+
#
|
|
960
|
+
#: () -> bool
|
|
725
961
|
def failure?
|
|
726
962
|
!success?
|
|
727
963
|
end
|
|
728
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
|
+
|
|
729
990
|
# Create a code units cache for the given encoding.
|
|
991
|
+
#
|
|
992
|
+
#: (Encoding encoding) -> _CodeUnitsCache
|
|
730
993
|
def code_units_cache(encoding)
|
|
731
994
|
source.code_units_cache(encoding)
|
|
732
995
|
end
|
|
@@ -734,41 +997,42 @@ module Prism
|
|
|
734
997
|
|
|
735
998
|
# This is a result specific to the `parse` and `parse_file` methods.
|
|
736
999
|
class ParseResult < Result
|
|
737
|
-
autoload :Comments, "prism/parse_result/comments"
|
|
738
1000
|
autoload :Errors, "prism/parse_result/errors"
|
|
739
1001
|
autoload :Newlines, "prism/parse_result/newlines"
|
|
740
1002
|
|
|
741
|
-
private_constant :Comments
|
|
742
1003
|
private_constant :Errors
|
|
743
1004
|
private_constant :Newlines
|
|
744
1005
|
|
|
745
1006
|
# The syntax tree that was parsed from the source code.
|
|
746
|
-
attr_reader :value
|
|
1007
|
+
attr_reader :value #: ProgramNode
|
|
747
1008
|
|
|
748
1009
|
# Create a new parse result object with the given values.
|
|
749
|
-
|
|
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)
|
|
750
1013
|
@value = value
|
|
751
|
-
super(
|
|
1014
|
+
super(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
752
1015
|
end
|
|
753
1016
|
|
|
754
1017
|
# Implement the hash pattern matching interface for ParseResult.
|
|
755
|
-
|
|
1018
|
+
#
|
|
1019
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1020
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
756
1021
|
super.merge!(value: value)
|
|
757
1022
|
end
|
|
758
1023
|
|
|
759
|
-
# Attach the list of comments to their respective locations in the tree.
|
|
760
|
-
def attach_comments!
|
|
761
|
-
Comments.new(self).attach! # steep:ignore
|
|
762
|
-
end
|
|
763
|
-
|
|
764
1024
|
# Walk the tree and mark nodes that are on a new line, loosely emulating
|
|
765
1025
|
# the behavior of CRuby's `:line` tracepoint event.
|
|
1026
|
+
#
|
|
1027
|
+
#: () -> void
|
|
766
1028
|
def mark_newlines!
|
|
767
1029
|
value.accept(Newlines.new(source.offsets.size)) # steep:ignore
|
|
768
1030
|
end
|
|
769
1031
|
|
|
770
1032
|
# Returns a string representation of the syntax tree with the errors
|
|
771
1033
|
# displayed inline.
|
|
1034
|
+
#
|
|
1035
|
+
#: () -> String
|
|
772
1036
|
def errors_format
|
|
773
1037
|
Errors.new(self).format
|
|
774
1038
|
end
|
|
@@ -777,16 +1041,20 @@ module Prism
|
|
|
777
1041
|
# This is a result specific to the `lex` and `lex_file` methods.
|
|
778
1042
|
class LexResult < Result
|
|
779
1043
|
# The list of tokens that were parsed from the source code.
|
|
780
|
-
attr_reader :value
|
|
1044
|
+
attr_reader :value #: Array[Token]
|
|
781
1045
|
|
|
782
1046
|
# Create a new lex result object with the given values.
|
|
783
|
-
|
|
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)
|
|
784
1050
|
@value = value
|
|
785
|
-
super(
|
|
1051
|
+
super(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
786
1052
|
end
|
|
787
1053
|
|
|
788
1054
|
# Implement the hash pattern matching interface for LexResult.
|
|
789
|
-
|
|
1055
|
+
#
|
|
1056
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1057
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
790
1058
|
super.merge!(value: value)
|
|
791
1059
|
end
|
|
792
1060
|
end
|
|
@@ -795,16 +1063,20 @@ module Prism
|
|
|
795
1063
|
class ParseLexResult < Result
|
|
796
1064
|
# A tuple of the syntax tree and the list of tokens that were parsed from
|
|
797
1065
|
# the source code.
|
|
798
|
-
attr_reader :value
|
|
1066
|
+
attr_reader :value #: [ProgramNode, Array[Token]]
|
|
799
1067
|
|
|
800
1068
|
# Create a new parse lex result object with the given values.
|
|
801
|
-
|
|
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)
|
|
802
1072
|
@value = value
|
|
803
|
-
super(
|
|
1073
|
+
super(magic_comments, data_loc, errors, warnings, continuable, source)
|
|
804
1074
|
end
|
|
805
1075
|
|
|
806
1076
|
# Implement the hash pattern matching interface for ParseLexResult.
|
|
807
|
-
|
|
1077
|
+
#
|
|
1078
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1079
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
808
1080
|
super.merge!(value: value)
|
|
809
1081
|
end
|
|
810
1082
|
end
|
|
@@ -812,29 +1084,38 @@ module Prism
|
|
|
812
1084
|
# This represents a token from the Ruby source.
|
|
813
1085
|
class Token
|
|
814
1086
|
# The Source object that represents the source this token came from.
|
|
815
|
-
attr_reader :source
|
|
1087
|
+
attr_reader :source #: Source
|
|
816
1088
|
private :source
|
|
817
1089
|
|
|
818
1090
|
# The type of token that this token is.
|
|
819
|
-
attr_reader :type
|
|
1091
|
+
attr_reader :type #: Symbol
|
|
820
1092
|
|
|
821
1093
|
# A byteslice of the source that this token represents.
|
|
822
|
-
attr_reader :value
|
|
1094
|
+
attr_reader :value #: String
|
|
1095
|
+
|
|
1096
|
+
# @rbs @location: Location | Integer
|
|
823
1097
|
|
|
824
1098
|
# Create a new token object with the given type, value, and location.
|
|
825
|
-
|
|
1099
|
+
#
|
|
1100
|
+
#: (Source source, Symbol type, String value, Location | Integer location, Integer state) -> void
|
|
1101
|
+
def initialize(source, type, value, location, state)
|
|
826
1102
|
@source = source
|
|
827
1103
|
@type = type
|
|
828
1104
|
@value = value
|
|
829
1105
|
@location = location
|
|
1106
|
+
@state = state
|
|
830
1107
|
end
|
|
831
1108
|
|
|
832
1109
|
# Implement the hash pattern matching interface for Token.
|
|
833
|
-
|
|
1110
|
+
#
|
|
1111
|
+
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
1112
|
+
def deconstruct_keys(keys) # :nodoc:
|
|
834
1113
|
{ type: type, value: value, location: location }
|
|
835
1114
|
end
|
|
836
1115
|
|
|
837
1116
|
# A Location object representing the location of this token in the source.
|
|
1117
|
+
#
|
|
1118
|
+
#: () -> Location
|
|
838
1119
|
def location
|
|
839
1120
|
location = @location
|
|
840
1121
|
return location if location.is_a?(Location)
|
|
@@ -842,7 +1123,9 @@ module Prism
|
|
|
842
1123
|
end
|
|
843
1124
|
|
|
844
1125
|
# Implement the pretty print interface for Token.
|
|
845
|
-
|
|
1126
|
+
#
|
|
1127
|
+
#: (PP q) -> void
|
|
1128
|
+
def pretty_print(q) # :nodoc:
|
|
846
1129
|
q.group do
|
|
847
1130
|
q.text(type.to_s)
|
|
848
1131
|
self.location.pretty_print(q)
|
|
@@ -857,6 +1140,8 @@ module Prism
|
|
|
857
1140
|
end
|
|
858
1141
|
|
|
859
1142
|
# Returns true if the given other token is equal to this token.
|
|
1143
|
+
#
|
|
1144
|
+
#: (untyped other) -> bool
|
|
860
1145
|
def ==(other)
|
|
861
1146
|
Token === other &&
|
|
862
1147
|
other.type == type &&
|
|
@@ -864,17 +1149,42 @@ module Prism
|
|
|
864
1149
|
end
|
|
865
1150
|
|
|
866
1151
|
# Returns a string representation of this token.
|
|
867
|
-
|
|
1152
|
+
#
|
|
1153
|
+
#: () -> String
|
|
1154
|
+
def inspect # :nodoc:
|
|
868
1155
|
location
|
|
869
1156
|
super
|
|
870
1157
|
end
|
|
871
1158
|
|
|
872
1159
|
# Freeze this object and the objects it contains.
|
|
1160
|
+
#
|
|
1161
|
+
#: () -> void
|
|
873
1162
|
def deep_freeze
|
|
874
1163
|
value.freeze
|
|
875
1164
|
location.freeze
|
|
876
1165
|
freeze
|
|
877
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
|
|
878
1188
|
end
|
|
879
1189
|
|
|
880
1190
|
# This object is passed to the various Prism.* methods that accept the
|
|
@@ -884,14 +1194,16 @@ module Prism
|
|
|
884
1194
|
class Scope
|
|
885
1195
|
# The list of local variables that are defined in this scope. This should be
|
|
886
1196
|
# defined as an array of symbols.
|
|
887
|
-
attr_reader :locals
|
|
1197
|
+
attr_reader :locals #: Array[Symbol]
|
|
888
1198
|
|
|
889
1199
|
# The list of local variables that are forwarded to the next scope. This
|
|
890
1200
|
# should by defined as an array of symbols containing the specific values of
|
|
891
1201
|
# :*, :**, :&, or :"...".
|
|
892
|
-
attr_reader :forwarding
|
|
1202
|
+
attr_reader :forwarding #: Array[Symbol]
|
|
893
1203
|
|
|
894
1204
|
# Create a new scope object with the given locals and forwarding.
|
|
1205
|
+
#
|
|
1206
|
+
#: (Array[Symbol] locals, Array[Symbol] forwarding) -> void
|
|
895
1207
|
def initialize(locals, forwarding)
|
|
896
1208
|
@locals = locals
|
|
897
1209
|
@forwarding = forwarding
|
|
@@ -901,6 +1213,8 @@ module Prism
|
|
|
901
1213
|
# Create a new scope with the given locals and forwarding options that is
|
|
902
1214
|
# suitable for passing into one of the Prism.* methods that accepts the
|
|
903
1215
|
# `scopes` option.
|
|
1216
|
+
#
|
|
1217
|
+
#: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope
|
|
904
1218
|
def self.scope(locals: [], forwarding: [])
|
|
905
1219
|
Scope.new(locals, forwarding)
|
|
906
1220
|
end
|