steep 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,45 +44,55 @@ module Steep
44
44
  end
45
45
  end
46
46
 
47
+ def self.parse(source_code, path:, factory:)
48
+ Source.parse(source_code, path: path.to_s, factory: factory, labeling: ASTUtils::Labeling.new)
49
+ end
50
+
51
+ def self.type_check(source, subtyping:)
52
+ typing = Typing.new
53
+
54
+ if source
55
+ annotations = source.annotations(block: source.node, factory: subtyping.factory, current_module: AST::Namespace.root)
56
+ const_env = TypeInference::ConstantEnv.new(factory: subtyping.factory, context: nil)
57
+ type_env = TypeInference::TypeEnv.build(annotations: annotations,
58
+ subtyping: subtyping,
59
+ const_env: const_env,
60
+ signatures: subtyping.factory.env)
61
+
62
+ construction = TypeConstruction.new(
63
+ checker: subtyping,
64
+ annotations: annotations,
65
+ source: source,
66
+ context: TypeInference::Context.new(
67
+ block_context: nil,
68
+ module_context: TypeInference::Context::ModuleContext.new(
69
+ instance_type: nil,
70
+ module_type: nil,
71
+ implement_name: nil,
72
+ current_namespace: AST::Namespace.root,
73
+ const_env: const_env,
74
+ class_name: nil
75
+ ),
76
+ method_context: nil,
77
+ break_context: nil,
78
+ self_type: AST::Builtin::Object.instance_type,
79
+ type_env: type_env
80
+ ),
81
+ typing: typing
82
+ )
83
+
84
+ construction.synthesize(source.node)
85
+ end
86
+
87
+ typing
88
+ end
89
+
47
90
  def type_check(subtyping, env_updated_at)
48
91
  # skip type check
49
92
  return false if status.is_a?(TypeCheckStatus) && env_updated_at <= status.timestamp
50
93
 
51
94
  parse(subtyping.factory) do |source|
52
- typing = Typing.new
53
-
54
- if source
55
- annotations = source.annotations(block: source.node, factory: subtyping.factory, current_module: AST::Namespace.root)
56
- const_env = TypeInference::ConstantEnv.new(factory: subtyping.factory, context: nil)
57
- type_env = TypeInference::TypeEnv.build(annotations: annotations,
58
- subtyping: subtyping,
59
- const_env: const_env,
60
- signatures: subtyping.factory.env)
61
-
62
- construction = TypeConstruction.new(
63
- checker: subtyping,
64
- annotations: annotations,
65
- source: source,
66
- context: TypeInference::Context.new(
67
- block_context: nil,
68
- module_context: TypeInference::Context::ModuleContext.new(
69
- instance_type: nil,
70
- module_type: nil,
71
- implement_name: nil,
72
- current_namespace: AST::Namespace.root,
73
- const_env: const_env,
74
- class_name: nil
75
- ),
76
- method_context: nil,
77
- break_context: nil,
78
- self_type: AST::Builtin::Object.instance_type,
79
- type_env: type_env
80
- ),
81
- typing: typing
82
- )
83
-
84
- construction.synthesize(source.node)
85
- end
95
+ typing = self.class.type_check(source, subtyping: subtyping)
86
96
 
87
97
  @status = TypeCheckStatus.new(
88
98
  typing: typing,
@@ -100,7 +110,7 @@ module Steep
100
110
  if status.is_a?(TypeCheckStatus)
101
111
  yield status.source
102
112
  else
103
- yield Source.parse(content, path: path.to_s, factory: factory, labeling: ASTUtils::Labeling.new)
113
+ yield self.class.parse(content, path: path, factory: factory)
104
114
  end
105
115
  rescue AnnotationParser::SyntaxError => exn
106
116
  Steep.logger.warn { "Annotation syntax error on #{path}: #{exn.inspect}" }
@@ -708,8 +708,15 @@ module Steep
708
708
  when :return
709
709
  yield_self do
710
710
  if node.children.size > 0
711
+ method_return_type = expand_alias(method_context&.return_type)
712
+
711
713
  return_types = node.children.map do |value|
712
- synthesize(value)
714
+ synthesize(value,
715
+ hint: if method_return_type.is_a?(AST::Types::Void)
716
+ nil
717
+ else
718
+ method_return_type
719
+ end)
713
720
  end
714
721
 
715
722
  value_type = if return_types.size == 1
@@ -718,9 +725,9 @@ module Steep
718
725
  AST::Builtin::Array.instance_type(union_type(*return_types))
719
726
  end
720
727
 
721
- if (ret_type = expand_alias(method_context&.return_type))
722
- unless ret_type.is_a?(AST::Types::Void)
723
- result = check_relation(sub_type: value_type, super_type: ret_type)
728
+ if method_return_type
729
+ unless method_return_type.is_a?(AST::Types::Void)
730
+ result = check_relation(sub_type: value_type, super_type: method_return_type)
724
731
 
725
732
  if result.failure?
726
733
  typing.add_error(Errors::ReturnTypeMismatch.new(node: node,
@@ -941,9 +948,9 @@ module Steep
941
948
  if constructor.module_context&.implement_name && !namespace_module?(node)
942
949
  constructor.validate_method_definitions(node, constructor.module_context.implement_name)
943
950
  end
944
- end
945
951
 
946
- typing.add_typing(node, AST::Builtin.nil_type, context)
952
+ typing.add_typing(node, AST::Builtin.nil_type, constructor.context)
953
+ end
947
954
  end
948
955
 
949
956
  when :module
@@ -954,9 +961,9 @@ module Steep
954
961
  if constructor.module_context&.implement_name && !namespace_module?(node)
955
962
  constructor.validate_method_definitions(node, constructor.module_context.implement_name)
956
963
  end
957
- end
958
964
 
959
- typing.add_typing(node, AST::Builtin.nil_type, context)
965
+ typing.add_typing(node, AST::Builtin.nil_type, constructor.context)
966
+ end
960
967
  end
961
968
 
962
969
  when :self
data/lib/steep/typing.rb CHANGED
@@ -1,5 +1,16 @@
1
1
  module Steep
2
2
  class Typing
3
+ class UnknownNodeError < StandardError
4
+ attr_reader :op
5
+ attr_reader :node
6
+
7
+ def initialize(op, node:)
8
+ @op = op
9
+ @node = node
10
+ super "Unknown node for #{op}: #{node.inspect}"
11
+ end
12
+ end
13
+
3
14
  attr_reader :errors
4
15
  attr_reader :typing
5
16
  attr_reader :parent
@@ -48,7 +59,7 @@ module Steep
48
59
  if parent
49
60
  parent.type_of(node: node)
50
61
  else
51
- raise "Unknown node for typing: #{node.inspect}"
62
+ raise UnknownNodeError.new(:type, node: node)
52
63
  end
53
64
  end
54
65
  end
@@ -62,7 +73,7 @@ module Steep
62
73
  if parent
63
74
  parent.context_of(node: node)
64
75
  else
65
- raise "Unknown node for context: #{node.inspect}"
76
+ raise UnknownNodeError.new(:context, node: node)
66
77
  end
67
78
  end
68
79
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.13.0"
2
+ VERSION = "0.14.0"
3
3
  end
data/smoke/alias/a.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # @type var x: foo
2
2
  x = ""
3
3
 
4
- # !expects ArgumentTypeMismatch: receiver=(::Integer | ::String), expected=::String, actual=::Integer
4
+ # !expects ArgumentTypeMismatch: receiver=(::Integer | ::String), expected=::string, actual=::Integer
5
5
  x + 123
6
6
 
7
7
  # @type var y: bar
data/smoke/regexp/b.rb CHANGED
@@ -12,11 +12,11 @@
12
12
  match_ref_3.foo
13
13
 
14
14
  match_ref_4 = match[0, 1]
15
- # !expects NoMethodError: type=::Array[::String], method=foo
15
+ # !expects NoMethodError: type=::Array[(::String | nil)], method=foo
16
16
  match_ref_4.foo
17
17
 
18
18
  match_ref_5 = match[0..1]
19
- # !expects NoMethodError: type=::Array[::String], method=foo
19
+ # !expects NoMethodError: type=::Array[(::String | nil)], method=foo
20
20
  match_ref_5.foo
21
21
 
22
22
  begin_1 = match.begin(0)
@@ -32,7 +32,7 @@
32
32
  begin_3.foo
33
33
 
34
34
  captures_1 = match.captures
35
- # !expects NoMethodError: type=::Array[::String], method=foo
35
+ # !expects NoMethodError: type=::Array[(::String | nil)], method=foo
36
36
  captures_1.foo
37
37
 
38
38
  end_1 = match.end(0)
@@ -92,7 +92,7 @@
92
92
  string_1.foo
93
93
 
94
94
  to_a_1 = match.to_a
95
- # !expects NoMethodError: type=::Array[::String], method=foo
95
+ # !expects NoMethodError: type=::Array[(::String | nil)], method=foo
96
96
  to_a_1.foo
97
97
 
98
98
  values_at_1 = match.values_at
@@ -9,16 +9,17 @@ Rake::TestTask.new(:test) do |t|
9
9
  end
10
10
  end
11
11
 
12
- task :default => [:test, :stdlib_test, :rubocop, :validate]
12
+ multitask :default => [:test, :stdlib_test, :rubocop, :validate]
13
13
 
14
- task :validate do
14
+ task :validate => :parser do
15
15
  sh "rbs validate"
16
16
  end
17
17
 
18
- task :stdlib_test do
19
- FileList["test/stdlib/*_test.rb"].each do |test|
18
+ FileList["test/stdlib/*_test.rb"].each do |test|
19
+ multitask test => :parser do
20
20
  sh "ruby bin/test_runner.rb #{test}"
21
21
  end
22
+ multitask stdlib_test: test
22
23
  end
23
24
 
24
25
  task :rubocop do
@@ -20,8 +20,8 @@
20
20
  - Use `bin/annotate-with-rdoc stdlib/path/to/signature.rbs` to annotate the RBS files.
21
21
  - Committing the generated annotations is recommended.
22
22
  6. Fix method types and comments.
23
- - The auto generated RDoc comments include `argslist` section, which we don't expect to be included the RBS files.
24
- - Delete the `argslist` sections.
23
+ - The auto generated RDoc comments include `arglists` section, which we don't expect to be included the RBS files.
24
+ - Delete the `arglists` sections.
25
25
  - Give methods correct types.
26
26
  - Write tests, if possible. (If it is too difficult to write test, skip it.)
27
27
 
@@ -50,7 +50,7 @@ You may find the *Good for first contributor* column where you can find some cla
50
50
  * You can use --method-owner if you want to print method of other classes too, for documentation purpose.
51
51
  * `bin/annotate-with-rdoc stdlib/builtin/string.rbs`
52
52
  * Write comments using RDoc.
53
- * It contains argslist section, but I don't think we should have it in RBS files.
53
+ * It contains arglists section, but I don't think we should have it in RBS files.
54
54
  * `bin/query-rdoc String#initialize`
55
55
  * Print RDoc documents in the format you can copy-and-paste to RBS.
56
56
  * `bin/sort stdlib/builtin/string.rbs`
@@ -23,7 +23,7 @@ module Ruby
23
23
  loader.add(path: Pathname(dir))
24
24
  end
25
25
 
26
- loader.no_builtin! nil if no_stdlib
26
+ loader.no_builtin! if no_stdlib
27
27
 
28
28
  loader
29
29
  end
@@ -37,7 +37,7 @@ module Ruby
37
37
  @stderr = stderr
38
38
  end
39
39
 
40
- COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :version]
40
+ COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :version, :parse]
41
41
 
42
42
  def library_parse(opts, options:)
43
43
  opts.on("-r LIBRARY") do |lib|
@@ -523,6 +523,27 @@ module Ruby
523
523
  end
524
524
  end
525
525
 
526
+ def run_parse(args, options)
527
+ loader = EnvironmentLoader.new()
528
+
529
+ syntax_error = false
530
+ args.each do |path|
531
+ path = Pathname(path)
532
+ loader.each_signature(path) do |sig_path|
533
+ Parser.parse_signature(sig_path.read)
534
+ rescue Ruby::Signature::Parser::SyntaxError => ex
535
+ loc = ex.error_value.location
536
+ stdout.puts "#{sig_path}:#{loc.start_line}:#{loc.start_column}: parse error on value: (#{ex.token_str})"
537
+ syntax_error = true
538
+ rescue Ruby::Signature::Parser::SemanticsError => ex
539
+ loc = ex.location
540
+ stdout.puts "#{sig_path}:#{loc.start_line}:#{loc.start_column}: #{ex.original_message}"
541
+ syntax_error = true
542
+ end
543
+ end
544
+ exit 1 if syntax_error
545
+ end
546
+
526
547
  def parse_type_name(string)
527
548
  Namespace.parse(string).yield_self do |namespace|
528
549
  last = namespace.path.last
@@ -1330,11 +1330,12 @@ class SyntaxError < StandardError
1330
1330
  end
1331
1331
 
1332
1332
  class SemanticsError < StandardError
1333
- attr_reader :subject
1333
+ attr_reader :subject, :location, :original_message
1334
1334
 
1335
1335
  def initialize(message, subject:, location:)
1336
1336
  @subject = subject
1337
1337
  @location = location
1338
+ @original_message = message
1338
1339
 
1339
1340
  super "parse error on #{location}: #{message}"
1340
1341
  end
@@ -210,6 +210,9 @@ module Ruby
210
210
  end
211
211
  end
212
212
  end
213
+ each_child node do |child|
214
+ process child, namespace: namespace, current_module: current_module, comments: comments, singleton: singleton
215
+ end
213
216
 
214
217
  when :CDECL
215
218
  type_name = case
@@ -59,6 +59,7 @@ module Ruby
59
59
  spy = self
60
60
 
61
61
  object.singleton_class.class_eval do
62
+ remove_method spy.method_name
62
63
  define_method spy.method_name, spy.spy()
63
64
  end
64
65
  end
@@ -154,6 +155,7 @@ module Ruby
154
155
  spy = self
155
156
 
156
157
  mod.class_eval do
158
+ remove_method spy.method_name
157
159
  define_method spy.method_name, spy.spy()
158
160
  end
159
161
  end
@@ -162,6 +164,7 @@ module Ruby
162
164
  spy = self
163
165
 
164
166
  mod.class_eval do
167
+ remove_method spy.method_name
165
168
  define_method spy.method_name, spy.original_method
166
169
  end
167
170
  end
@@ -1,141 +1,271 @@
1
- class MatchData < Object
2
- def ==: (untyped arg0) -> bool
1
+ # MatchData encapsulates the result of matching a Regexp against string. It is
2
+ # returned by Regexp#match and String#match, and also stored in a global
3
+ # variable returned by Regexp.last_match.
4
+ #
5
+ # Usage:
6
+ #
7
+ # url = 'https://docs.ruby-lang.org/en/2.5.0/MatchData.html'
8
+ # m = url.match(/(\d\.?)+/) # => #<MatchData "2.5.0" 1:"0">
9
+ # m.string # => "https://docs.ruby-lang.org/en/2.5.0/MatchData.html"
10
+ # m.regexp # => /(\d\.?)+/
11
+ # # entire matched substring:
12
+ # m[0] # => "2.5.0"
13
+ #
14
+ # # Working with unnamed captures
15
+ # m = url.match(%r{([^/]+)/([^/]+)\.html$})
16
+ # m.captures # => ["2.5.0", "MatchData"]
17
+ # m[1] # => "2.5.0"
18
+ # m.values_at(1, 2) # => ["2.5.0", "MatchData"]
19
+ #
20
+ # # Working with named captures
21
+ # m = url.match(%r{(?<version>[^/]+)/(?<module>[^/]+)\.html$})
22
+ # m.captures # => ["2.5.0", "MatchData"]
23
+ # m.named_captures # => {"version"=>"2.5.0", "module"=>"MatchData"}
24
+ # m[:version] # => "2.5.0"
25
+ # m.values_at(:version, :module)
26
+ # # => ["2.5.0", "MatchData"]
27
+ # # Numerical indexes are working, too
28
+ # m[1] # => "2.5.0"
29
+ # m.values_at(1, 2) # => ["2.5.0", "MatchData"]
30
+ #
31
+ # ## Global variables equivalence
32
+ #
33
+ # Parts of last MatchData (returned by Regexp.last_match) are also aliased as
34
+ # global variables:
35
+ #
36
+ # * `$~` is Regexp.last_match;
37
+ # * `$&` is [Regexp.last_match](0);
38
+ # * `$1`, `$2`, and so on are [Regexp.last_match](i) (captures by number);
39
+ # * `$`` is Regexp.last_match`.pre_match`;
40
+ # * `$'` is Regexp.last_match`.post_match`;
41
+ # * `$+` is [Regexp.last_match](-1) (the last capture).
42
+ #
43
+ #
44
+ # See also "Special global variables" section in Regexp documentation.
45
+ #
46
+ class MatchData
47
+ public
3
48
 
4
- def []: (Integer i_or_start_or_range_or_name) -> String?
5
- | (Integer i_or_start_or_range_or_name, ?Integer length) -> ::Array[String]
6
- | (::Range[Integer] i_or_start_or_range_or_name) -> ::Array[String]
7
- | (String | Symbol i_or_start_or_range_or_name) -> String?
49
+ # Equality---Two matchdata are equal if their target strings, patterns, and
50
+ # matched positions are identical.
51
+ #
52
+ def ==: (untyped other) -> bool
8
53
 
9
- def begin: (Integer | String | Symbol n) -> Integer?
54
+ # Match Reference -- MatchData acts as an array, and may be accessed using the
55
+ # normal array indexing techniques. `mtch[0]` is equivalent to the special
56
+ # variable `$&`, and returns the entire matched string. `mtch[1]`, `mtch[2]`,
57
+ # and so on return the values of the matched backreferences (portions of the
58
+ # pattern between parentheses).
59
+ #
60
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
61
+ # m #=> #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
62
+ # m[0] #=> "HX1138"
63
+ # m[1, 2] #=> ["H", "X"]
64
+ # m[1..3] #=> ["H", "X", "113"]
65
+ # m[-3, 2] #=> ["X", "113"]
66
+ #
67
+ # m = /(?<foo>a+)b/.match("ccaaab")
68
+ # m #=> #<MatchData "aaab" foo:"aaa">
69
+ # m["foo"] #=> "aaa"
70
+ # m[:foo] #=> "aaa"
71
+ #
72
+ def []: (Integer idx) -> String?
73
+ | (Integer start, Integer length) -> ::Array[String?]
74
+ | (::Range[Integer] range) -> ::Array[String?]
75
+ | (String | Symbol name) -> String?
10
76
 
11
- # Returns the array of captures; equivalent to `mtch.to_a[1..-1]` .
12
- #
13
- # ```ruby
14
- # f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
15
- # f1 #=> "H"
16
- # f2 #=> "X"
17
- # f3 #=> "113"
18
- # f4 #=> "8"
19
- # ```
20
- def captures: () -> ::Array[String]
77
+ # Returns the offset of the start of the *n*th element of the match array in the
78
+ # string. *n* can be a string or symbol to reference a named capture.
79
+ #
80
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
81
+ # m.begin(0) #=> 1
82
+ # m.begin(2) #=> 2
83
+ #
84
+ # m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
85
+ # p m.begin(:foo) #=> 0
86
+ # p m.begin(:bar) #=> 2
87
+ #
88
+ def begin: (Integer | String | Symbol n_or_name) -> Integer?
21
89
 
22
- def `end`: (Integer | String | Symbol n) -> Integer?
90
+ # Returns the array of captures; equivalent to `mtch.to_a[1..-1]`.
91
+ #
92
+ # f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
93
+ # f1 #=> "H"
94
+ # f2 #=> "X"
95
+ # f3 #=> "113"
96
+ # f4 #=> "8"
97
+ #
98
+ def captures: () -> ::Array[String?]
23
99
 
100
+ # Returns the offset of the character immediately following the end of the *n*th
101
+ # element of the match array in the string. *n* can be a string or symbol to
102
+ # reference a named capture.
103
+ #
104
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
105
+ # m.end(0) #=> 7
106
+ # m.end(2) #=> 3
107
+ #
108
+ # m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
109
+ # p m.end(:foo) #=> 1
110
+ # p m.end(:bar) #=> 3
111
+ #
112
+ def `end`: (Integer | String | Symbol n_or_name) -> Integer?
113
+
114
+ # Equality---Two matchdata are equal if their target strings, patterns, and
115
+ # matched positions are identical.
116
+ #
24
117
  def eql?: (untyped other) -> bool
25
118
 
26
- # Produce a hash based on the target string, regexp and matched positions
27
- # of this matchdata.
28
- #
29
- # See also Object\#hash.
119
+ # Produce a hash based on the target string, regexp and matched positions of
120
+ # this matchdata.
121
+ #
122
+ # See also Object#hash.
123
+ #
30
124
  def hash: () -> Integer
31
125
 
126
+ # Returns a printable version of *mtch*.
127
+ #
128
+ # puts /.$/.match("foo").inspect
129
+ # #=> #<MatchData "o">
130
+ #
131
+ # puts /(.)(.)(.)/.match("foo").inspect
132
+ # #=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">
133
+ #
134
+ # puts /(.)(.)?(.)/.match("fo").inspect
135
+ # #=> #<MatchData "fo" 1:"f" 2:nil 3:"o">
136
+ #
137
+ # puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
138
+ # #=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">
139
+ #
32
140
  def inspect: () -> String
33
141
 
34
142
  # Returns the number of elements in the match array.
35
- #
36
- # ```ruby
37
- # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
38
- # m.length #=> 5
39
- # m.size #=> 5
40
- # ```
143
+ #
144
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
145
+ # m.length #=> 5
146
+ # m.size #=> 5
147
+ #
41
148
  def length: () -> Integer
42
149
 
43
- # Returns a [Hash](https://ruby-doc.org/core-2.6.3/Hash.html) using named
44
- # capture.
45
- #
46
- # A key of the hash is a name of the named captures. A value of the hash
47
- # is a string of last successful capture of corresponding group.
48
- #
49
- # ```ruby
50
- # m = /(?.)(?.)/.match("01")
51
- # m.named_captures #=> {"a" => "0", "b" => "1"}
52
- #
53
- # m = /(?.)(?.)?/.match("0")
54
- # m.named_captures #=> {"a" => "0", "b" => nil}
55
- #
56
- # m = /(?.)(?.)/.match("01")
57
- # m.named_captures #=> {"a" => "1"}
58
- #
59
- # m = /(?x)|(?y)/.match("x")
60
- # m.named_captures #=> {"a" => "x"}
61
- # ```
150
+ # Returns a Hash using named capture.
151
+ #
152
+ # A key of the hash is a name of the named captures. A value of the hash is a
153
+ # string of last successful capture of corresponding group.
154
+ #
155
+ # m = /(?<a>.)(?<b>.)/.match("01")
156
+ # m.named_captures #=> {"a" => "0", "b" => "1"}
157
+ #
158
+ # m = /(?<a>.)(?<b>.)?/.match("0")
159
+ # m.named_captures #=> {"a" => "0", "b" => nil}
160
+ #
161
+ # m = /(?<a>.)(?<a>.)/.match("01")
162
+ # m.named_captures #=> {"a" => "1"}
163
+ #
164
+ # m = /(?<a>x)|(?<a>y)/.match("x")
165
+ # m.named_captures #=> {"a" => "x"}
166
+ #
62
167
  def named_captures: () -> ::Hash[String, String?]
63
168
 
169
+ # Returns a list of names of captures as an array of strings. It is same as
170
+ # mtch.regexp.names.
171
+ #
172
+ # /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").names
173
+ # #=> ["foo", "bar", "baz"]
174
+ #
175
+ # m = /(?<x>.)(?<y>.)?/.match("a") #=> #<MatchData "a" x:"a" y:nil>
176
+ # m.names #=> ["x", "y"]
177
+ #
64
178
  def names: () -> ::Array[String]
65
179
 
66
- def offset: (Integer | Symbol | String n) -> ([Integer, Integer] | [nil, nil])
180
+ # Returns a two-element array containing the beginning and ending offsets of the
181
+ # *n*th match. *n* can be a string or symbol to reference a named capture.
182
+ #
183
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
184
+ # m.offset(0) #=> [1, 7]
185
+ # m.offset(4) #=> [6, 7]
186
+ #
187
+ # m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
188
+ # p m.offset(:foo) #=> [0, 1]
189
+ # p m.offset(:bar) #=> [2, 3]
190
+ #
191
+ def offset: (Integer | Symbol | String n_or_name) -> ([ Integer, Integer ] | [ nil, nil ])
67
192
 
68
- # Returns the portion of the original string after the current match.
69
- # Equivalent to the special variable `$'` .
70
- #
71
- # ```ruby
72
- # m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
73
- # m.post_match #=> ": The Movie"
74
- # ```
193
+ # Returns the portion of the original string after the current match. Equivalent
194
+ # to the special variable `$'`.
195
+ #
196
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
197
+ # m.post_match #=> ": The Movie"
198
+ #
75
199
  def post_match: () -> String
76
200
 
77
201
  # Returns the portion of the original string before the current match.
78
- # Equivalent to the special variable `` $` `` .
79
- #
80
- # ```ruby
81
- # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
82
- # m.pre_match #=> "T"
83
- # ```
202
+ # Equivalent to the special variable `$``.
203
+ #
204
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
205
+ # m.pre_match #=> "T"
206
+ #
84
207
  def pre_match: () -> String
85
208
 
86
209
  # Returns the regexp.
87
- #
88
- # ```ruby
89
- # m = /a.*b/.match("abc")
90
- # m.regexp #=> /a.*b/
91
- # ```
210
+ #
211
+ # m = /a.*b/.match("abc")
212
+ # m.regexp #=> /a.*b/
213
+ #
92
214
  def regexp: () -> Regexp
93
215
 
94
216
  # Returns the number of elements in the match array.
95
- #
96
- # ```ruby
97
- # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
98
- # m.length #=> 5
99
- # m.size #=> 5
100
- # ```
217
+ #
218
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
219
+ # m.length #=> 5
220
+ # m.size #=> 5
221
+ #
101
222
  def size: () -> Integer
102
223
 
103
- # Returns a frozen copy of the string passed in to `match` .
104
- #
105
- # ```ruby
106
- # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
107
- # m.string #=> "THX1138."
108
- # ```
224
+ # Returns a frozen copy of the string passed in to `match`.
225
+ #
226
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
227
+ # m.string #=> "THX1138."
228
+ #
109
229
  def string: () -> String
110
230
 
111
231
  # Returns the array of matches.
112
- #
113
- # ```ruby
114
- # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
115
- # m.to_a #=> ["HX1138", "H", "X", "113", "8"]
116
- # ```
117
- #
118
- # Because `to_a` is called when expanding `*` *variable* , there’s a
119
- # useful assignment shortcut for extracting matched fields. This is
120
- # slightly slower than accessing the fields directly (as an intermediate
121
- # array is generated).
122
- #
123
- # ```ruby
124
- # all,f1,f2,f3 = * /(.)(.)(\d+)(\d)/.match("THX1138.")
125
- # all #=> "HX1138"
126
- # f1 #=> "H"
127
- # f2 #=> "X"
128
- # f3 #=> "113"
129
- # ```
130
- def to_a: () -> ::Array[String]
232
+ #
233
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
234
+ # m.to_a #=> ["HX1138", "H", "X", "113", "8"]
235
+ #
236
+ # Because `to_a` is called when expanding `*`*variable*, there's a useful
237
+ # assignment shortcut for extracting matched fields. This is slightly slower
238
+ # than accessing the fields directly (as an intermediate array is generated).
239
+ #
240
+ # all,f1,f2,f3 = * /(.)(.)(\d+)(\d)/.match("THX1138.")
241
+ # all #=> "HX1138"
242
+ # f1 #=> "H"
243
+ # f2 #=> "X"
244
+ # f3 #=> "113"
245
+ #
246
+ def to_a: () -> ::Array[String?]
131
247
 
132
248
  # Returns the entire matched string.
133
- #
134
- # ```ruby
135
- # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
136
- # m.to_s #=> "HX1138"
137
- # ```
249
+ #
250
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138.")
251
+ # m.to_s #=> "HX1138"
252
+ #
138
253
  def to_s: () -> String
139
254
 
140
- def values_at: (*Integer | Symbol | String indexes) -> ::Array[String?]
255
+ # Uses each *index* to access the matching values, returning an array of the
256
+ # corresponding matches.
257
+ #
258
+ # m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
259
+ # m.to_a #=> ["HX1138", "H", "X", "113", "8"]
260
+ # m.values_at(0, 2, -2) #=> ["HX1138", "X", "113"]
261
+ #
262
+ # m = /(?<a>\d+) *(?<op>[+\-*\/]) *(?<b>\d+)/.match("1 + 2")
263
+ # m.to_a #=> ["1 + 2", "1", "+", "2"]
264
+ # m.values_at(:a, :b, :op) #=> ["1", "2", "+"]
265
+ #
266
+ def values_at: (*Integer | Symbol | String n_or_name) -> ::Array[String?]
267
+
268
+ private
269
+
270
+ def initialize_copy: (self object) -> void
141
271
  end