steep 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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