rbs 3.0.0.dev.2 → 3.0.0.dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +2 -1
  3. data/.github/workflows/ruby.yml +4 -0
  4. data/Gemfile.lock +11 -11
  5. data/Rakefile +2 -2
  6. data/Steepfile +1 -1
  7. data/core/array.rbs +573 -423
  8. data/core/basic_object.rbs +11 -39
  9. data/core/binding.rbs +1 -1
  10. data/core/builtin.rbs +8 -0
  11. data/core/class.rbs +37 -0
  12. data/core/comparable.rbs +7 -18
  13. data/core/complex.rbs +2 -2
  14. data/core/data.rbs +419 -0
  15. data/core/dir.rbs +52 -104
  16. data/core/encoding.rbs +22 -181
  17. data/core/enumerable.rbs +212 -175
  18. data/core/enumerator/product.rbs +96 -0
  19. data/core/enumerator.rbs +57 -8
  20. data/core/errors.rbs +8 -2
  21. data/core/exception.rbs +41 -0
  22. data/core/fiber.rbs +95 -12
  23. data/core/file.rbs +840 -275
  24. data/core/file_test.rbs +34 -19
  25. data/core/float.rbs +40 -96
  26. data/core/gc.rbs +15 -3
  27. data/core/hash.rbs +113 -175
  28. data/core/integer.rbs +85 -145
  29. data/core/io/buffer.rbs +187 -60
  30. data/core/io/wait.rbs +28 -16
  31. data/core/io.rbs +1859 -1389
  32. data/core/kernel.rbs +525 -961
  33. data/core/match_data.rbs +306 -142
  34. data/core/math.rbs +506 -234
  35. data/core/method.rbs +0 -24
  36. data/core/module.rbs +110 -17
  37. data/core/nil_class.rbs +2 -0
  38. data/core/numeric.rbs +76 -144
  39. data/core/object.rbs +88 -212
  40. data/core/proc.rbs +17 -5
  41. data/core/process.rbs +22 -5
  42. data/core/ractor.rbs +1 -1
  43. data/core/random.rbs +20 -3
  44. data/core/range.rbs +91 -89
  45. data/core/rational.rbs +2 -3
  46. data/core/rbs/unnamed/argf.rbs +177 -120
  47. data/core/rbs/unnamed/env_class.rbs +89 -163
  48. data/core/rbs/unnamed/random.rbs +36 -12
  49. data/core/refinement.rbs +8 -0
  50. data/core/regexp.rbs +462 -272
  51. data/core/ruby_vm.rbs +210 -0
  52. data/{stdlib/set/0 → core}/set.rbs +43 -47
  53. data/core/string.rbs +1403 -1332
  54. data/core/string_io.rbs +191 -107
  55. data/core/struct.rbs +67 -63
  56. data/core/symbol.rbs +187 -201
  57. data/core/thread.rbs +40 -35
  58. data/core/time.rbs +902 -826
  59. data/core/trace_point.rbs +55 -6
  60. data/core/unbound_method.rbs +48 -24
  61. data/docs/collection.md +4 -0
  62. data/docs/syntax.md +55 -0
  63. data/ext/rbs_extension/parser.c +5 -6
  64. data/lib/rbs/cli.rb +6 -1
  65. data/lib/rbs/collection/cleaner.rb +8 -1
  66. data/lib/rbs/collection/config/lockfile.rb +3 -1
  67. data/lib/rbs/collection/config/lockfile_generator.rb +16 -14
  68. data/lib/rbs/collection/config.rb +1 -1
  69. data/lib/rbs/collection/sources/git.rb +9 -2
  70. data/lib/rbs/collection/sources/local.rb +79 -0
  71. data/lib/rbs/collection/sources.rb +8 -1
  72. data/lib/rbs/environment.rb +6 -5
  73. data/lib/rbs/environment_loader.rb +3 -2
  74. data/lib/rbs/errors.rb +18 -0
  75. data/lib/rbs/locator.rb +26 -7
  76. data/lib/rbs/sorter.rb +2 -2
  77. data/lib/rbs/version.rb +1 -1
  78. data/sig/collection/sources.rbs +32 -3
  79. data/sig/environment.rbs +2 -3
  80. data/sig/locator.rbs +14 -2
  81. data/sig/shims/{abstract_syntax_tree.rbs → _abstract_syntax_tree.rbs} +0 -0
  82. data/stdlib/bigdecimal/0/big_decimal.rbs +16 -13
  83. data/stdlib/cgi/0/core.rbs +16 -0
  84. data/stdlib/coverage/0/coverage.rbs +50 -8
  85. data/stdlib/csv/0/csv.rbs +1 -1
  86. data/stdlib/date/0/date.rbs +856 -726
  87. data/stdlib/date/0/date_time.rbs +83 -210
  88. data/stdlib/erb/0/erb.rbs +13 -36
  89. data/stdlib/etc/0/etc.rbs +127 -20
  90. data/stdlib/fileutils/0/fileutils.rbs +1290 -381
  91. data/stdlib/logger/0/logger.rbs +466 -316
  92. data/stdlib/net-http/0/net-http.rbs +2211 -534
  93. data/stdlib/nkf/0/nkf.rbs +5 -5
  94. data/stdlib/objspace/0/objspace.rbs +31 -14
  95. data/stdlib/openssl/0/openssl.rbs +11 -7
  96. data/stdlib/optparse/0/optparse.rbs +20 -17
  97. data/stdlib/pathname/0/pathname.rbs +21 -4
  98. data/stdlib/pstore/0/pstore.rbs +378 -154
  99. data/stdlib/pty/0/pty.rbs +24 -8
  100. data/stdlib/ripper/0/ripper.rbs +1650 -0
  101. data/stdlib/socket/0/addrinfo.rbs +9 -15
  102. data/stdlib/socket/0/socket.rbs +36 -3
  103. data/stdlib/strscan/0/string_scanner.rbs +7 -5
  104. data/stdlib/tempfile/0/tempfile.rbs +104 -44
  105. data/stdlib/time/0/time.rbs +2 -2
  106. data/stdlib/uri/0/file.rbs +5 -0
  107. data/stdlib/uri/0/generic.rbs +2 -2
  108. data/stdlib/yaml/0/yaml.rbs +2 -2
  109. data/stdlib/zlib/0/zlib.rbs +1 -1
  110. metadata +8 -6
  111. data/core/deprecated.rbs +0 -9
  112. data/sig/shims/ripper.rbs +0 -8
data/core/trace_point.rbs CHANGED
@@ -114,7 +114,7 @@ class TracePoint < Object
114
114
 
115
115
  # <!--
116
116
  # rdoc-file=trace_point.rb
117
- # - TracePoint.allow_reentry
117
+ # - TracePoint.allow_reentry { block }
118
118
  # -->
119
119
  # In general, while a TracePoint callback is running, other registered callbacks
120
120
  # are not called to avoid confusion by reentrance. This method allows the
@@ -124,6 +124,54 @@ class TracePoint < Object
124
124
  # If this method is called when the reentrance is already allowed, it raises a
125
125
  # RuntimeError.
126
126
  #
127
+ # **Example:**
128
+ #
129
+ # # Without reentry
130
+ # # ---------------
131
+ #
132
+ # line_handler = TracePoint.new(:line) do |tp|
133
+ # next if tp.path != __FILE__ # only work in this file
134
+ # puts "Line handler"
135
+ # binding.eval("class C; end")
136
+ # end.enable
137
+ #
138
+ # class_handler = TracePoint.new(:class) do |tp|
139
+ # puts "Class handler"
140
+ # end.enable
141
+ #
142
+ # class B
143
+ # end
144
+ #
145
+ # # This script will print "Class handler" only once: when inside :line
146
+ # # handler, all other handlers are ignored
147
+ #
148
+ # # With reentry
149
+ # # ------------
150
+ #
151
+ # line_handler = TracePoint.new(:line) do |tp|
152
+ # next if tp.path != __FILE__ # only work in this file
153
+ # next if (__LINE__..__LINE__+3).cover?(tp.lineno) # don't be invoked from itself
154
+ # puts "Line handler"
155
+ # TracePoint.allow_reentry { binding.eval("class C; end") }
156
+ # end.enable
157
+ #
158
+ # class_handler = TracePoint.new(:class) do |tp|
159
+ # puts "Class handler"
160
+ # end.enable
161
+ #
162
+ # class B
163
+ # end
164
+ #
165
+ # # This wil print "Class handler" twice: inside allow_reentry block in :line
166
+ # # handler, other handlers are enabled.
167
+ #
168
+ # Note that the example shows the principal effect of the method, but its
169
+ # practical usage is for debugging libraries that sometimes require other
170
+ # libraries hooks to not be affected by debugger being inside trace point
171
+ # handling. Precautions should be taken against infinite recursion in this case
172
+ # (note that we needed to filter out calls by itself from :line handler,
173
+ # otherwise it will call itself infinitely).
174
+ #
127
175
  def self.allow_reentry: () { () -> void } -> void
128
176
 
129
177
  # <!--
@@ -163,7 +211,7 @@ class TracePoint < Object
163
211
  # binding of the nearest Ruby method calling the C method, since C methods
164
212
  # themselves do not have bindings.
165
213
  #
166
- def binding: () -> Binding
214
+ def binding: () -> Binding?
167
215
 
168
216
  # <!--
169
217
  # rdoc-file=trace_point.rb
@@ -251,7 +299,7 @@ class TracePoint < Object
251
299
  # <!--
252
300
  # rdoc-file=trace_point.rb
253
301
  # - trace.enable(target: nil, target_line: nil, target_thread: nil) -> true or false
254
- # - trace.enable(target: nil, target_line: nil, target_thread: nil) { block } -> obj
302
+ # - trace.enable(target: nil, target_line: nil, target_thread: :default) { block } -> obj
255
303
  # -->
256
304
  # Activates the trace.
257
305
  #
@@ -264,15 +312,16 @@ class TracePoint < Object
264
312
  # trace.enable #=> true (previous state)
265
313
  # # trace is still enabled
266
314
  #
267
- # If a block is given, the trace will only be enabled within the scope of the
268
- # block.
315
+ # If a block is given, the trace will only be enabled during the block call. If
316
+ # target and target_line are both nil, then target_thread will default to the
317
+ # current thread if a block is given.
269
318
  #
270
319
  # trace.enabled?
271
320
  # #=> false
272
321
  #
273
322
  # trace.enable do
274
323
  # trace.enabled?
275
- # # only enabled for this block
324
+ # # only enabled for this block and thread
276
325
  # end
277
326
  #
278
327
  # trace.enabled?
@@ -46,6 +46,22 @@
46
46
  # um.bind(t).call #=> :original
47
47
  #
48
48
  class UnboundMethod
49
+ # <!--
50
+ # rdoc-file=proc.c
51
+ # - meth.eql?(other_meth) -> true or false
52
+ # - meth == other_meth -> true or false
53
+ # -->
54
+ # Two unbound method objects are equal if they refer to the same method
55
+ # definition.
56
+ #
57
+ # Array.instance_method(:each_slice) == Enumerable.instance_method(:each_slice)
58
+ # #=> true
59
+ #
60
+ # Array.instance_method(:sum) == Enumerable.instance_method(:sum)
61
+ # #=> false, Array redefines the method for efficiency
62
+ #
63
+ def ==: (untyped) -> bool
64
+
49
65
  # <!--
50
66
  # rdoc-file=proc.c
51
67
  # - method.clone -> new_method
@@ -141,6 +157,38 @@ class UnboundMethod
141
157
  #
142
158
  def bind: (untyped obj) -> Method
143
159
 
160
+ # <!--
161
+ # rdoc-file=proc.c
162
+ # - meth.to_s -> string
163
+ # - meth.inspect -> string
164
+ # -->
165
+ # Returns a human-readable description of the underlying method.
166
+ #
167
+ # "cat".method(:count).inspect #=> "#<Method: String#count(*)>"
168
+ # (1..3).method(:map).inspect #=> "#<Method: Range(Enumerable)#map()>"
169
+ #
170
+ # In the latter case, the method description includes the "owner" of the
171
+ # original method (`Enumerable` module, which is included into `Range`).
172
+ #
173
+ # `inspect` also provides, when possible, method argument names (call sequence)
174
+ # and source location.
175
+ #
176
+ # require 'net/http'
177
+ # Net::HTTP.method(:get).inspect
178
+ # #=> "#<Method: Net::HTTP.get(uri_or_host, path=..., port=...) <skip>/lib/ruby/2.7.0/net/http.rb:457>"
179
+ #
180
+ # `...` in argument definition means argument is optional (has some default
181
+ # value).
182
+ #
183
+ # For methods defined in C (language core and extensions), location and argument
184
+ # names can't be extracted, and only generic information is provided in form of
185
+ # `*` (any number of arguments) or `_` (some positional argument).
186
+ #
187
+ # "cat".method(:count).inspect #=> "#<Method: String#count(*)>"
188
+ # "cat".method(:+).inspect #=> "#<Method: String#+(_)>""
189
+ #
190
+ def inspect: () -> String
191
+
144
192
  # <!--
145
193
  # rdoc-file=proc.c
146
194
  # - meth.name -> symbol
@@ -188,30 +236,6 @@ class UnboundMethod
188
236
  def parameters: () -> ::Array[[ Symbol, Symbol ]]
189
237
  | () -> ::Array[[ Symbol ]]
190
238
 
191
- # <!--
192
- # rdoc-file=proc.c
193
- # - meth.private? -> true or false
194
- # -->
195
- # Returns whether the method is private.
196
- #
197
- def private?: () -> bool
198
-
199
- # <!--
200
- # rdoc-file=proc.c
201
- # - meth.protected? -> true or false
202
- # -->
203
- # Returns whether the method is protected.
204
- #
205
- def protected?: () -> bool
206
-
207
- # <!--
208
- # rdoc-file=proc.c
209
- # - meth.public? -> true or false
210
- # -->
211
- # Returns whether the method is public.
212
- #
213
- def public?: () -> bool
214
-
215
239
  # <!--
216
240
  # rdoc-file=proc.c
217
241
  # - meth.source_location -> [String, Integer]
data/docs/collection.md CHANGED
@@ -79,6 +79,10 @@ sources:
79
79
  revision: main
80
80
  repo_dir: gems
81
81
 
82
+ # You can also add a local path as a collection source optionaly.
83
+ - type: local
84
+ path: path/to/local/dir
85
+
82
86
  # A directory to install the downloaded RBSs
83
87
  path: .gem_rbs_collection
84
88
 
data/docs/syntax.md CHANGED
@@ -501,6 +501,8 @@ private alias foo bar # Syntax error
501
501
  ```markdown
502
502
  _decl_ ::= _class-decl_ # Class declaration
503
503
  | _module-decl_ # Module declaration
504
+ | _class-alias-decl_ # Class alias declaration
505
+ | _module-alias-decl_ # Module alias declaration
504
506
  | _interface-decl_ # Interface declaration
505
507
  | _type-alias-decl_ # Type alias declaration
506
508
  | _const-decl_ # Constant declaration
@@ -512,6 +514,10 @@ _class-decl_ ::= `class` _class-name_ _module-type-parameters_ _members_ `end`
512
514
  _module-decl_ ::= `module` _module-name_ _module-type-parameters_ _members_ `end`
513
515
  | `module` _module-name_ _module-type-parameters_ `:` _module-self-types_ _members_ `end`
514
516
 
517
+ _class-alias-decl_ ::= `class` _class-name_ `=` _class-name_
518
+
519
+ _module-alias-decl_ ::= `module` _module-name_ `=` _module-name_
520
+
515
521
  _module-self-types_ ::= _class-name_ _type-arguments_ `,` _module-self-types_ (Class instance)
516
522
  | _interface-name_ _type-arguments_ `,` _module-self-types_ (Interface)
517
523
 
@@ -554,6 +560,32 @@ end
554
560
 
555
561
  The `Enumerable` module above requires `each` method for enumerating objects.
556
562
 
563
+ ### Class/module alias declaration
564
+
565
+ An alias of a class or module can be defined in RBS.
566
+
567
+ ```rbs
568
+ module Foo = Kernel
569
+
570
+ class Bar = Array
571
+ ```
572
+
573
+ The syntax defines a class and the definition is equivalent to the right-hand-side.
574
+
575
+ ```
576
+ class Baz < Bar[String] # Class alias can be inherited
577
+ include Foo # Module alias can be included
578
+ end
579
+ ```
580
+
581
+ This is a definition corresponding to the following Ruby code.
582
+
583
+ ```ruby
584
+ Foo = Kernel
585
+
586
+ Bar = Array
587
+ ```
588
+
557
589
  ### Interface declaration
558
590
 
559
591
  Interface declaration can have parameters but allows only a few of the members.
@@ -696,6 +728,29 @@ type int_printer = PrettyPrint[Integer] # Type error
696
728
 
697
729
  The upper bound must be one of a class instance type, interface type, or class singleton type.
698
730
 
731
+ ### Directives
732
+
733
+ Directives are placed at the top of a file and provides per-file-basis features.
734
+
735
+ ```
736
+ _use-directive_ ::= `use` _use-clauses_
737
+
738
+ _use-clauses_ ::= _use-clause_ `,` ... `,` _use-clause_
739
+
740
+ _use-clause_ ::= _type-name_ # Single use clause
741
+ | _type-name_ `as` _simple-type-name_ # Single use clause with alias
742
+ | _namespace_ # Wildcard use clause
743
+ ```
744
+
745
+ The *use directive* defines relative type names that is an alias of other type names.
746
+ We can use the simple type names if it is declared with *use*.
747
+
748
+ ```
749
+ use RBS::Namespace # => Defines `Namespace`
750
+ use RBS::TypeName as TN # => Defines `TN`
751
+ use RBS::AST::* # => Defines modules under `::RBS::AST::` namespace
752
+ ```
753
+
699
754
  ### Comments
700
755
 
701
756
  You can write single line comments. Comments must be on their own line. Comments can lead with whitespace.
@@ -2724,13 +2724,12 @@ VALUE parse_signature(parserstate *state) {
2724
2724
  VALUE dirs = rb_ary_new();
2725
2725
  VALUE decls = rb_ary_new();
2726
2726
 
2727
+ while (state->next_token.type == kUSE) {
2728
+ rb_ary_push(dirs, parse_use_directive(state));
2729
+ }
2730
+
2727
2731
  while (state->next_token.type != pEOF) {
2728
- if (state->next_token.type == kUSE) {
2729
- VALUE use = parse_use_directive(state);
2730
- rb_ary_push(dirs, use);
2731
- } else {
2732
- rb_ary_push(decls, parse_decl(state));
2733
- }
2732
+ rb_ary_push(decls, parse_decl(state));
2734
2733
  }
2735
2734
 
2736
2735
  VALUE ret = rb_ary_new();
data/lib/rbs/cli.rb CHANGED
@@ -1076,11 +1076,16 @@ EOB
1076
1076
  config_path.write(<<~'YAML')
1077
1077
  # Download sources
1078
1078
  sources:
1079
- - name: ruby/gem_rbs_collection
1079
+ - type: git
1080
+ name: ruby/gem_rbs_collection
1080
1081
  remote: https://github.com/ruby/gem_rbs_collection.git
1081
1082
  revision: main
1082
1083
  repo_dir: gems
1083
1084
 
1085
+ # You can specify local directories as sources also.
1086
+ # - type: local
1087
+ # path: path/to/your/local/repository
1088
+
1084
1089
  # A directory to install the downloaded RBSs
1085
1090
  path: .gem_rbs_collection
1086
1091
 
@@ -16,7 +16,14 @@ module RBS
16
16
  version or raise
17
17
  next if needed? gem_name, version
18
18
 
19
- FileUtils.remove_entry_secure(dir.to_s)
19
+ case
20
+ when dir.symlink?
21
+ dir.unlink
22
+ when dir.directory?
23
+ FileUtils.remove_entry_secure(dir.to_s)
24
+ else
25
+ raise
26
+ end
20
27
  end
21
28
  end
22
29
 
@@ -75,7 +75,7 @@ module RBS
75
75
  if gems = data["gems"]
76
76
  gems.each do |gem|
77
77
  src = gem["source"]
78
- source = Sources.from_config_entry(src)
78
+ source = Sources.from_config_entry(src, base_directory: lockfile_path.dirname)
79
79
  lockfile.gems[gem["name"]] = {
80
80
  name: gem["name"],
81
81
  version: gem["version"],
@@ -106,6 +106,8 @@ module RBS
106
106
  meta_path = fullpath.join(gem[:name], gem[:version], Sources::Git::METADATA_FILENAME)
107
107
  raise CollectionNotAvailable unless meta_path.exist?
108
108
  raise CollectionNotAvailable unless library_data(gem) == YAML.load(meta_path.read)
109
+ when Sources::Local
110
+ raise CollectionNotAvailable unless fullpath.join(gem[:name], gem[:version]).symlink?
109
111
  end
110
112
  end
111
113
  end
@@ -105,27 +105,29 @@ module RBS
105
105
  unless locked
106
106
  source =
107
107
  if src_data
108
- Sources.from_config_entry(src_data)
108
+ Sources.from_config_entry(src_data, base_directory: config.config_path.dirname)
109
109
  else
110
- find_source(name: name) or return
110
+ find_source(name: name)
111
111
  end
112
112
 
113
- installed_version = version
114
- best_version = find_best_version(version: installed_version, versions: source.versions(name))
113
+ if source
114
+ installed_version = version
115
+ best_version = find_best_version(version: installed_version, versions: source.versions(name))
115
116
 
116
- locked = {
117
- name: name,
118
- version: best_version.to_s,
119
- source: source,
120
- }
117
+ locked = {
118
+ name: name,
119
+ version: best_version.to_s,
120
+ source: source,
121
+ }
122
+ end
121
123
  end
122
124
 
123
- locked or raise
124
-
125
- lockfile.gems[name] = locked
125
+ if locked
126
+ lockfile.gems[name] = locked
126
127
 
127
- locked[:source].dependencies_of(locked[:name], locked[:version])&.each do |dep|
128
- assign_stdlib(name: dep["name"], from_gem: name)
128
+ locked[:source].dependencies_of(locked[:name], locked[:version])&.each do |dep|
129
+ assign_stdlib(name: dep["name"], from_gem: name)
130
+ end
129
131
  end
130
132
 
131
133
  gem_hash[name].dependencies.each do |dep|
@@ -66,7 +66,7 @@ module RBS
66
66
  def sources
67
67
  @sources ||= (
68
68
  @data['sources']
69
- .map { |c| Sources.from_config_entry(c) }
69
+ .map { |c| Sources.from_config_entry(c, base_directory: @config_path.dirname) }
70
70
  .push(Sources::Stdlib.instance)
71
71
  .push(Sources::Rubygems.instance)
72
72
  )
@@ -45,7 +45,12 @@ module RBS
45
45
 
46
46
  gem_dir = dest.join(name, version)
47
47
 
48
- if gem_dir.directory?
48
+ case
49
+ when gem_dir.symlink?
50
+ stdout.puts "Updating to #{format_config_entry(name, version)} from a local source"
51
+ gem_dir.unlink
52
+ _install(dest: dest, name: name, version: version)
53
+ when gem_dir.directory?
49
54
  prev = load_metadata(dir: gem_dir)
50
55
 
51
56
  if prev == metadata_content(name: name, version: version)
@@ -55,9 +60,11 @@ module RBS
55
60
  FileUtils.remove_entry_secure(gem_dir.to_s)
56
61
  _install(dest: dest, name: name, version: version)
57
62
  end
58
- else
63
+ when !gem_dir.exist?
59
64
  stdout.puts "Installing #{format_config_entry(name, version)}"
60
65
  _install(dest: dest, name: name, version: version)
66
+ else
67
+ raise
61
68
  end
62
69
  end
63
70
 
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ module Collection
5
+ module Sources
6
+ class Local
7
+ include Base
8
+
9
+ attr_reader :path, :full_path
10
+
11
+ def initialize(path:, base_directory:)
12
+ # TODO: resolve relative path from dir of rbs_collection.yaml
13
+ @path = Pathname(path)
14
+ @full_path = base_directory / path
15
+ end
16
+
17
+ def has?(name, version)
18
+ if version
19
+ @full_path.join(name, version).directory?
20
+ else
21
+ not versions(name).empty?
22
+ end
23
+ end
24
+
25
+ def versions(name)
26
+ @full_path.join(name).glob('*/').map { |path| path.basename.to_s }
27
+ end
28
+
29
+ # Create a symlink instead of copying file to refer files in @path.
30
+ # By avoiding copying RBS files, the users do not need re-run `rbs collection install`
31
+ # when the RBS files are updated.
32
+ def install(dest:, name:, version:, stdout:)
33
+ from = @full_path.join(name, version)
34
+ gem_dir = dest.join(name, version)
35
+
36
+ case
37
+ when gem_dir.symlink? && gem_dir.readlink == from
38
+ stdout.puts "Using #{name}:#{version} (#{from})"
39
+ when gem_dir.symlink?
40
+ prev = gem_dir.readlink
41
+ gem_dir.unlink
42
+ _install(from, dest.join(name, version))
43
+ stdout.puts "Updating #{name}:#{version} to #{from} from #{prev}"
44
+ when gem_dir.directory?
45
+ # TODO: Show version of git source
46
+ FileUtils.remove_entry_secure(gem_dir.to_s)
47
+ _install(from, dest.join(name, version))
48
+ stdout.puts "Updating #{name}:#{version} from git source"
49
+ when !gem_dir.exist?
50
+ _install(from, dest.join(name, version))
51
+ stdout.puts "Installing #{name}:#{version} (#{from})"
52
+ else
53
+ raise
54
+ end
55
+ end
56
+
57
+ private def _install(src, dst)
58
+ dst.dirname.mkpath
59
+ File.symlink(src, dst)
60
+ end
61
+
62
+ def manifest_of(name, version)
63
+ gem_dir = @full_path.join(name, version)
64
+ raise unless gem_dir.exist?
65
+
66
+ manifest_path = gem_dir.join('manifest.yaml')
67
+ YAML.safe_load(manifest_path.read) if manifest_path.exist?
68
+ end
69
+
70
+ def to_lockfile
71
+ {
72
+ 'type' => 'local',
73
+ 'path' => @path.to_s,
74
+ }
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -4,11 +4,12 @@ require_relative './sources/base'
4
4
  require_relative './sources/git'
5
5
  require_relative './sources/stdlib'
6
6
  require_relative './sources/rubygems'
7
+ require_relative './sources/local'
7
8
 
8
9
  module RBS
9
10
  module Collection
10
11
  module Sources
11
- def self.from_config_entry(source_entry)
12
+ def self.from_config_entry(source_entry, base_directory:)
12
13
  case source_entry['type']
13
14
  when 'git', nil # git source by default
14
15
  # @type var source_entry: Git::source_entry
@@ -18,6 +19,12 @@ module RBS
18
19
  remote: source_entry["remote"],
19
20
  repo_dir: source_entry["repo_dir"]
20
21
  )
22
+ when 'local'
23
+ # @type var source_entry: Local::source_entry
24
+ Local.new(
25
+ path: source_entry['path'],
26
+ base_directory: base_directory,
27
+ )
21
28
  when 'stdlib'
22
29
  Stdlib.instance
23
30
  when 'rubygems'
@@ -773,13 +773,14 @@ module RBS
773
773
  hash
774
774
  end
775
775
 
776
- def reject
776
+ def unload(buffers)
777
777
  env = Environment.new
778
778
 
779
- declarations.each do |decl|
780
- unless yield(decl)
781
- env << decl
782
- end
779
+ buffers_decls.each do |buf, decls|
780
+ next if buffers.include?(buf)
781
+
782
+ dirs = buffer_directives.fetch(buf)
783
+ env.add_signature(buffer: buf, directives: dirs, decls: decls)
783
784
  end
784
785
 
785
786
  env
@@ -47,8 +47,9 @@ module RBS
47
47
  when path
48
48
  dirs << path
49
49
  when library
50
- if library == 'rubygems'
51
- RBS.logger.warn '`rubygems` has been moved to core library, so it is always loaded. Remove explicit loading `rubygems`'
50
+ case library
51
+ when 'rubygems', 'set'
52
+ RBS.logger.warn "`#{library}` has been moved to core library, so it is always loaded. Remove explicit loading `#{library}`"
52
53
  return
53
54
  end
54
55
 
data/lib/rbs/errors.rb CHANGED
@@ -20,7 +20,25 @@ module RBS
20
20
  class LoadingError < BaseError; end
21
21
  class DefinitionError < BaseError; end
22
22
 
23
+ module DetailedMessageable
24
+ def detailed_message(highlight: false, **)
25
+ indent = " " * location.start_column
26
+ marker = "^" * (location.end_column - location.start_column)
27
+
28
+ io = StringIO.new
29
+ io.puts super
30
+ io.puts
31
+ io.print "\e[1m" if highlight
32
+ io.puts " #{location.buffer.lines[location.end_line - 1]}"
33
+ io.puts " #{indent}#{marker}"
34
+ io.print "\e[m" if highlight
35
+ io.string
36
+ end
37
+ end
38
+
23
39
  class ParsingError < BaseError
40
+ include DetailedMessageable
41
+
24
42
  attr_reader :location
25
43
  attr_reader :error_message
26
44
  attr_reader :token_type
data/lib/rbs/locator.rb CHANGED
@@ -2,21 +2,24 @@
2
2
 
3
3
  module RBS
4
4
  class Locator
5
- attr_reader :decls
5
+ attr_reader :decls, :dirs, :buffer
6
6
 
7
- def initialize(decls:)
7
+ def initialize(buffer:, dirs:, decls:)
8
+ @buffer = buffer
9
+ @dirs = dirs
8
10
  @decls = decls
9
11
  end
10
12
 
11
- def buffer
12
- decls[0].location&.buffer or raise
13
- end
14
-
15
13
  def find(line:, column:)
16
14
  pos = buffer.loc_to_pos([line, column])
17
15
 
16
+ dirs.each do |dir|
17
+ array = [] #: Array[component]
18
+ find_in_directive(pos, dir, array) and return array
19
+ end
20
+
18
21
  decls.each do |decl|
19
- array = []
22
+ array = [] #: Array[component]
20
23
  find_in_decl(pos, decl: decl, array: array) and return array
21
24
  end
22
25
 
@@ -36,6 +39,22 @@ module RBS
36
39
  end
37
40
  end
38
41
 
42
+ def find_in_directive(pos, dir, array)
43
+ if test_loc(pos, location: dir.location)
44
+ array.unshift(dir)
45
+
46
+ dir.clauses.each do |clause|
47
+ if test_loc(pos, location: clause.location)
48
+ array.unshift(clause)
49
+ find_in_loc(pos, location: clause.location, array: array)
50
+ return true
51
+ end
52
+ end
53
+ end
54
+
55
+ false
56
+ end
57
+
39
58
  def find_in_decl(pos, decl:, array:)
40
59
  if test_loc(pos, location: decl.location)
41
60
  array.unshift(decl)
data/lib/rbs/sorter.rb CHANGED
@@ -34,7 +34,7 @@ module RBS
34
34
  -3
35
35
  when Declarations::Constant
36
36
  -2
37
- when Declarations::Class, Declarations::Module
37
+ when Declarations::Class, Declarations::Module, Declarations::Interface
38
38
  -1
39
39
  when Members::Include
40
40
  0.0
@@ -102,7 +102,7 @@ module RBS
102
102
  member.name.to_s
103
103
  when Declarations::TypeAlias
104
104
  member.name.to_s
105
- when Declarations::Class, Declarations::Module
105
+ when Declarations::Class, Declarations::Module, Declarations::Interface
106
106
  member.name.to_s
107
107
  else
108
108
  raise