rbs 3.1.3 → 3.2.0.pre.1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +0 -6
  3. data/CHANGELOG.md +68 -0
  4. data/Gemfile +0 -6
  5. data/Gemfile.lock +12 -21
  6. data/README.md +1 -1
  7. data/Rakefile +44 -0
  8. data/Steepfile +3 -3
  9. data/core/array.rbs +0 -8
  10. data/core/builtin.rbs +28 -8
  11. data/core/constants.rbs +13 -5
  12. data/core/exception.rbs +1 -1
  13. data/core/global_variables.rbs +27 -27
  14. data/core/io.rbs +163 -172
  15. data/core/kernel.rbs +7 -4
  16. data/core/module.rbs +34 -32
  17. data/core/object.rbs +2 -2
  18. data/core/string_io.rbs +9 -0
  19. data/core/thread.rbs +25 -1
  20. data/core/time.rbs +3 -3
  21. data/docs/CONTRIBUTING.md +1 -1
  22. data/docs/rbs_by_example.md +16 -35
  23. data/docs/repo.md +1 -1
  24. data/docs/sigs.md +7 -7
  25. data/docs/stdlib.md +2 -3
  26. data/docs/syntax.md +40 -40
  27. data/lib/rbs/cli.rb +15 -4
  28. data/lib/rbs/collection/installer.rb +5 -2
  29. data/lib/rbs/collection/sources/stdlib.rb +5 -1
  30. data/lib/rbs/errors.rb +8 -1
  31. data/lib/rbs/file_finder.rb +1 -1
  32. data/lib/rbs/prototype/rb.rb +64 -6
  33. data/lib/rbs/prototype/rbi.rb +2 -6
  34. data/lib/rbs/prototype/runtime.rb +29 -8
  35. data/lib/rbs/subtractor.rb +17 -0
  36. data/lib/rbs/type_name.rb +4 -4
  37. data/lib/rbs/version.rb +1 -1
  38. data/rbs.gemspec +1 -1
  39. data/schema/decls.json +1 -1
  40. data/sig/errors.rbs +54 -0
  41. data/sig/parser.rbs +2 -2
  42. data/sig/prototype/rb.rbs +9 -1
  43. data/sig/subtractor.rbs +4 -0
  44. data/stdlib/logger/0/logger.rbs +1 -1
  45. data/stdlib/observable/0/observable.rbs +219 -0
  46. data/stdlib/uri/0/common.rbs +24 -0
  47. data/stdlib/zlib/0/buf_error.rbs +79 -0
  48. data/stdlib/zlib/0/data_error.rbs +79 -0
  49. data/stdlib/zlib/0/deflate.rbs +276 -0
  50. data/stdlib/zlib/0/error.rbs +89 -0
  51. data/stdlib/zlib/0/gzip_file/crc_error.rbs +115 -0
  52. data/stdlib/zlib/0/gzip_file/error.rbs +128 -0
  53. data/stdlib/zlib/0/gzip_file/length_error.rbs +115 -0
  54. data/stdlib/zlib/0/gzip_file/no_footer.rbs +114 -0
  55. data/stdlib/zlib/0/gzip_file.rbs +228 -0
  56. data/stdlib/zlib/0/gzip_reader.rbs +362 -0
  57. data/stdlib/zlib/0/gzip_writer.rbs +237 -0
  58. data/stdlib/zlib/0/inflate.rbs +249 -0
  59. data/stdlib/zlib/0/mem_error.rbs +79 -0
  60. data/stdlib/zlib/0/need_dict.rbs +82 -0
  61. data/stdlib/zlib/0/stream_end.rbs +80 -0
  62. data/stdlib/zlib/0/stream_error.rbs +80 -0
  63. data/stdlib/zlib/0/version_error.rbs +80 -0
  64. data/stdlib/zlib/0/zstream.rbs +270 -0
  65. metadata +24 -8
  66. data/stdlib/prime/0/integer-extension.rbs +0 -41
  67. data/stdlib/prime/0/manifest.yaml +0 -2
  68. data/stdlib/prime/0/prime.rbs +0 -372
@@ -9,6 +9,7 @@ module RBS
9
9
  attr_reader :env
10
10
  attr_reader :merge
11
11
  attr_reader :owners_included
12
+ attr_accessor :outline
12
13
 
13
14
  def initialize(patterns:, env:, merge:, owners_included: [])
14
15
  @patterns = patterns
@@ -19,6 +20,7 @@ module RBS
19
20
  @owners_included = owners_included.map do |name|
20
21
  Object.const_get(name)
21
22
  end
23
+ @outline = false
22
24
  end
23
25
 
24
26
  def target?(const)
@@ -378,7 +380,7 @@ module RBS
378
380
  RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
379
381
  nil
380
382
  else
381
- super_name = to_type_name(const_name(mod.superclass), full_name: true)
383
+ super_name = to_type_name(const_name(mod.superclass), full_name: true).absolute!
382
384
  super_args = type_args(super_name)
383
385
  AST::Declarations::Class::Super.new(name: super_name, args: super_args, location: nil)
384
386
  end
@@ -393,7 +395,7 @@ module RBS
393
395
  unless decl
394
396
  decl = AST::Declarations::Class.new(
395
397
  name: to_type_name(only_name(mod)),
396
- type_params: [],
398
+ type_params: type_params(mod),
397
399
  super_class: generate_super_class(mod),
398
400
  members: [],
399
401
  annotations: [],
@@ -426,7 +428,7 @@ module RBS
426
428
  )
427
429
  end
428
430
 
429
- generate_methods(mod, type_name, decl.members)
431
+ generate_methods(mod, type_name, decl.members) unless outline
430
432
 
431
433
  generate_constants mod, decl.members
432
434
  end
@@ -447,7 +449,7 @@ module RBS
447
449
  unless decl
448
450
  decl = AST::Declarations::Module.new(
449
451
  name: to_type_name(only_name(mod)),
450
- type_params: [],
452
+ type_params: type_params(mod),
451
453
  self_types: [],
452
454
  members: [],
453
455
  annotations: [],
@@ -480,7 +482,7 @@ module RBS
480
482
  )
481
483
  end
482
484
 
483
- generate_methods(mod, type_name, decl.members)
485
+ generate_methods(mod, type_name, decl.members) unless outline
484
486
 
485
487
  generate_constants mod, decl.members
486
488
  end
@@ -502,7 +504,7 @@ module RBS
502
504
  if outer_module.is_a?(Class)
503
505
  outer_decl = AST::Declarations::Class.new(
504
506
  name: to_type_name(outer_module_name),
505
- type_params: [],
507
+ type_params: type_params(outer_module),
506
508
  super_class: generate_super_class(outer_module),
507
509
  members: [],
508
510
  annotations: [],
@@ -512,7 +514,7 @@ module RBS
512
514
  else
513
515
  outer_decl = AST::Declarations::Module.new(
514
516
  name: to_type_name(outer_module_name),
515
- type_params: [],
517
+ type_params: type_params(outer_module),
516
518
  self_types: [],
517
519
  members: [],
518
520
  annotations: [],
@@ -539,7 +541,17 @@ module RBS
539
541
 
540
542
  def const_name(const)
541
543
  @module_name_method ||= Module.instance_method(:name)
542
- @module_name_method.bind(const).call
544
+ name = @module_name_method.bind(const).call
545
+ return nil unless name
546
+
547
+ begin
548
+ Object.const_get(name)
549
+ rescue NameError
550
+ # Should generate const name if anonymous or internal module (e.g. NameError::message)
551
+ nil
552
+ else
553
+ name
554
+ end
543
555
  end
544
556
 
545
557
  def type_args(type_name)
@@ -550,6 +562,15 @@ module RBS
550
562
  end
551
563
  end
552
564
 
565
+ def type_params(mod)
566
+ type_name = to_type_name(const_name(mod), full_name: true)
567
+ if class_decl = env.class_decls[type_name.absolute!]
568
+ class_decl.type_params
569
+ else
570
+ []
571
+ end
572
+ end
573
+
553
574
  def block_from_ast_of(method)
554
575
  return nil if RUBY_VERSION < '3.1'
555
576
 
@@ -51,6 +51,7 @@ module RBS
51
51
  context = _ = [context, decl.name]
52
52
  children = call(decl.each_decl.to_a, context: context) +
53
53
  decl.each_member.reject { |m| member_exist?(owner, m, context: context) }
54
+ children = filter_redundunt_access_modifiers(children)
54
55
  return nil if children.empty?
55
56
 
56
57
  update_decl(decl, members: children)
@@ -144,6 +145,22 @@ module RBS
144
145
  end
145
146
  end
146
147
 
148
+ private def filter_redundunt_access_modifiers(decls)
149
+ decls = decls.dup
150
+ decls.pop while access_modifier?(decls.last)
151
+ decls = decls.map.with_index do |decl, i|
152
+ if access_modifier?(decl) && access_modifier?(decls[i + 1])
153
+ nil
154
+ else
155
+ decl
156
+ end
157
+ end.compact
158
+ end
159
+
160
+ private def access_modifier?(decl)
161
+ decl.is_a?(AST::Members::Public) || decl.is_a?(AST::Members::Private)
162
+ end
163
+
147
164
  private def update_decl(decl, members:)
148
165
  case decl
149
166
  when AST::Declarations::Class
data/lib/rbs/type_name.rb CHANGED
@@ -9,12 +9,12 @@ module RBS
9
9
  def initialize(namespace:, name:)
10
10
  @namespace = namespace
11
11
  @name = name
12
- @kind = case name.to_s[0,1]
13
- when /[A-Z]/
12
+ @kind = case
13
+ when name.match?(/\A[A-Z]/)
14
14
  :class
15
- when /[a-z]/
15
+ when name.match?(/\A[a-z]/)
16
16
  :alias
17
- when "_"
17
+ when name.start_with?("_")
18
18
  :interface
19
19
  else
20
20
  # Defaults to :class
data/lib/rbs/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RBS
4
- VERSION = "3.1.3"
4
+ VERSION = "3.2.0.pre.1"
5
5
  end
data/rbs.gemspec CHANGED
@@ -35,5 +35,5 @@ Gem::Specification.new do |spec|
35
35
  spec.bindir = "exe"
36
36
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
37
  spec.require_paths = ["lib"]
38
- spec.required_ruby_version = ">= 2.6"
38
+ spec.required_ruby_version = ">= 3.0"
39
39
  end
data/schema/decls.json CHANGED
@@ -60,7 +60,7 @@
60
60
  "required": ["declaration", "name", "type", "comment", "location"]
61
61
  },
62
62
  "global": {
63
- "title": "Global declaration: `$DEBUG: bool`, ...",
63
+ "title": "Global declaration: `$DEBUG: boolish`, ...",
64
64
  "type": "object",
65
65
  "properties": {
66
66
  "declaration": {
data/sig/errors.rbs CHANGED
@@ -16,9 +16,23 @@ module RBS
16
16
  class BaseError < StandardError
17
17
  end
18
18
 
19
+ interface _Location
20
+ %a{pure} def location: () -> Location[untyped, untyped]?
21
+ end
22
+
23
+ interface _DetailedMessage
24
+ def detailed_message: (**untyped) -> String
25
+ end
26
+
27
+ module DetailedMessageable : _Location, _DetailedMessage
28
+ def detailed_message: (?highlight: boolish, **untyped) -> String
29
+ end
30
+
19
31
  # Error class for errors raised during parsing.
20
32
  #
21
33
  class ParsingError < BaseError
34
+ include DetailedMessageable
35
+
22
36
  attr_reader location: Location[untyped, untyped]
23
37
  attr_reader error_message: String
24
38
  attr_reader token_type: String
@@ -67,6 +81,8 @@ module RBS
67
81
  end
68
82
 
69
83
  class NoTypeFoundError < DefinitionError
84
+ include DetailedMessageable
85
+
70
86
  attr_reader type_name: TypeName
71
87
  attr_reader location: Location[untyped, untyped]?
72
88
 
@@ -85,6 +101,8 @@ module RBS
85
101
  end
86
102
 
87
103
  class NoSelfTypeFoundError < DefinitionError
104
+ include DetailedMessageable
105
+
88
106
  attr_reader type_name: TypeName
89
107
  attr_reader location: Location[untyped, untyped]?
90
108
 
@@ -96,6 +114,8 @@ module RBS
96
114
  end
97
115
 
98
116
  class NoMixinFoundError < DefinitionError
117
+ include DetailedMessageable
118
+
99
119
  attr_reader type_name: TypeName
100
120
  attr_reader member: AST::Members::t
101
121
 
@@ -107,6 +127,8 @@ module RBS
107
127
  end
108
128
 
109
129
  class DuplicatedMethodDefinitionError < DefinitionError
130
+ include DetailedMessageable
131
+
110
132
  type ty = Types::ClassSingleton | Types::ClassInstance | Types::Interface
111
133
  type original = DefinitionBuilder::MethodBuilder::Methods::Definition::original
112
134
 
@@ -143,6 +165,8 @@ module RBS
143
165
  # ```
144
166
  #
145
167
  class DuplicatedInterfaceMethodDefinitionError < DefinitionError
168
+ include DetailedMessageable
169
+
146
170
  type ty = Types::ClassSingleton | Types::ClassInstance | Types::Interface
147
171
  type mixin_member = AST::Members::Include | AST::Members::Extend
148
172
 
@@ -155,11 +179,15 @@ module RBS
155
179
  def type_name: () -> TypeName
156
180
 
157
181
  def qualified_method_name: () -> String
182
+
183
+ def location: () -> AST::Members::Mixin::loc?
158
184
  end
159
185
 
160
186
  # The `alias` member declares an alias from unknown method
161
187
  #
162
188
  class UnknownMethodAliasError < DefinitionError
189
+ include DetailedMessageable
190
+
163
191
  attr_reader type_name: TypeName
164
192
  attr_reader original_name: Symbol
165
193
  attr_reader aliased_name: Symbol
@@ -178,12 +206,16 @@ module RBS
178
206
  # The *overloading* method definition cannot find *non-overloading* method definition
179
207
  #
180
208
  class InvalidOverloadMethodError < DefinitionError
209
+ include DetailedMessageable
210
+
181
211
  attr_reader type_name: TypeName
182
212
  attr_reader method_name: Symbol
183
213
  attr_reader kind: :instance | :singleton
184
214
  attr_reader members: Array[AST::Members::MethodDefinition]
185
215
 
186
216
  def initialize: (type_name: TypeName, method_name: Symbol, kind: :instance | :singleton, members: Array[AST::Members::MethodDefinition]) -> void
217
+
218
+ def location: () -> AST::Members::MethodDefinition::loc?
187
219
  end
188
220
 
189
221
  class GenericParameterMismatchError < LoadingError
@@ -201,6 +233,8 @@ module RBS
201
233
  end
202
234
 
203
235
  class InvalidVarianceAnnotationError < DefinitionError
236
+ include DetailedMessageable
237
+
204
238
  attr_reader type_name: TypeName
205
239
  attr_reader param: AST::TypeParam
206
240
  attr_reader location: Location[untyped, untyped]?
@@ -209,6 +243,8 @@ module RBS
209
243
  end
210
244
 
211
245
  class RecursiveAliasDefinitionError < DefinitionError
246
+ include DetailedMessageable
247
+
212
248
  type ty = Types::ClassInstance | Types::ClassSingleton | Types::Interface
213
249
  type defn = DefinitionBuilder::MethodBuilder::Methods::Definition
214
250
 
@@ -223,6 +259,8 @@ module RBS
223
259
  # MixinClassError is raised if a include/prepend/extend has a class (not a module) to mix-in
224
260
  #
225
261
  class MixinClassError < DefinitionError
262
+ include DetailedMessageable
263
+
226
264
  type member = AST::Members::Include | AST::Members::Prepend | AST::Members::Extend
227
265
 
228
266
  attr_reader type_name: TypeName
@@ -240,6 +278,8 @@ module RBS
240
278
  # InheritModuleError is raised if a class definition inherits a module (not a class)
241
279
  #
242
280
  class InheritModuleError < DefinitionError
281
+ include DetailedMessageable
282
+
243
283
  attr_reader super_decl: AST::Declarations::Class::Super
244
284
 
245
285
  def initialize: (AST::Declarations::Class::Super) -> void
@@ -254,6 +294,8 @@ module RBS
254
294
  end
255
295
 
256
296
  class RecursiveTypeAliasError < BaseError
297
+ include DetailedMessageable
298
+
257
299
  attr_reader alias_names: Array[TypeName]
258
300
  attr_reader location: Location[untyped, untyped]?
259
301
 
@@ -263,6 +305,8 @@ module RBS
263
305
  end
264
306
 
265
307
  class NonregularTypeAliasError < BaseError
308
+ include DetailedMessageable
309
+
266
310
  # Diagnostic reported from `TypeAliasRegularity`.
267
311
  attr_reader diagnostic: TypeAliasRegularity::Diagnostic
268
312
 
@@ -273,6 +317,8 @@ module RBS
273
317
  end
274
318
 
275
319
  class CyclicTypeParameterBound < BaseError
320
+ include DetailedMessageable
321
+
276
322
  attr_reader location: Location[untyped, untyped]?
277
323
 
278
324
  # Array of parameters which contains cyclic dependencies.
@@ -295,16 +341,24 @@ module RBS
295
341
  # ```
296
342
  #
297
343
  class InconsistentClassModuleAliasError < BaseError
344
+ include DetailedMessageable
345
+
298
346
  attr_reader alias_entry: Environment::ModuleAliasEntry | Environment::ClassAliasEntry
299
347
 
300
348
  def initialize: (Environment::ModuleAliasEntry | Environment::ClassAliasEntry) -> void
349
+
350
+ def location: () -> AST::Declarations::AliasDecl::loc?
301
351
  end
302
352
 
303
353
  # A module/class alias declaration is cyclic
304
354
  #
305
355
  class CyclicClassAliasDefinitionError < BaseError
356
+ include DetailedMessageable
357
+
306
358
  attr_reader alias_entry: Environment::ModuleAliasEntry | Environment::ClassAliasEntry
307
359
 
308
360
  def initialize: (Environment::ModuleAliasEntry | Environment::ClassAliasEntry) -> void
361
+
362
+ def location: () -> AST::Declarations::AliasDecl::loc?
309
363
  end
310
364
  end
data/sig/parser.rbs CHANGED
@@ -2,7 +2,7 @@ module RBS
2
2
  class Parser
3
3
  # Parse a method type and return it
4
4
  #
5
- # When `range` keyword is specified, it starts parsing from the `begin` to the `endo` the range.
5
+ # When `range` keyword is specified, it starts parsing from the `begin` to the `end` of the range.
6
6
  #
7
7
  # ```ruby
8
8
  # RBS::Parser.parse_method_type("() -> void") # => `() -> void`
@@ -25,7 +25,7 @@ module RBS
25
25
 
26
26
  # Parse a type and return it
27
27
  #
28
- # When `range` keyword is specified, it starts parsing from the `begin` to the `endo` the range.
28
+ # When `range` keyword is specified, it starts parsing from the `begin` to the `end` of the range.
29
29
  #
30
30
  # ```ruby
31
31
  # RBS::Parser.parse_type("String") # => `String`
data/sig/prototype/rb.rbs CHANGED
@@ -12,12 +12,18 @@ module RBS
12
12
 
13
13
  attr_accessor namespace: Namespace
14
14
 
15
- def initialize: (module_function: bool, singleton: bool, namespace: Namespace) -> void
15
+ attr_accessor in_def: bool
16
+
17
+ def initialize: (module_function: bool, singleton: bool, namespace: Namespace, in_def: bool) -> void
16
18
 
17
19
  def method_kind: () -> method_kind
18
20
 
19
21
  def attribute_kind: () -> (:singleton | :instance)
20
22
 
23
+ def enter_namespace: (Namespace) -> Context
24
+
25
+ def update: (?module_function: bool, ?singleton: bool, ?in_def: bool) -> Context
26
+
21
27
  def self.initial: (?namespace: Namespace) -> Context
22
28
  end
23
29
 
@@ -83,6 +89,8 @@ module RBS
83
89
  def is_accessibility?: (decl) -> bool
84
90
 
85
91
  def find_def_index_by_name: (Array[decl] decls, Symbol name) -> [Integer, AST::Members::MethodDefinition | AST::Members::AttrReader | AST::Members::AttrWriter]?
92
+
93
+ def sort_members!: (Array[decl] decls) -> void
86
94
  end
87
95
  end
88
96
  end
data/sig/subtractor.rbs CHANGED
@@ -24,6 +24,10 @@ module RBS
24
24
 
25
25
  private def mixin_exist?: (TypeName owner, AST::Members::Include | AST::Members::Extend | AST::Members::Prepend, context: Resolver::context) -> boolish
26
26
 
27
+ private def filter_redundunt_access_modifiers: (Array[AST::Declarations::t | AST::Members::t]) -> Array[AST::Declarations::t | AST::Members::t]
28
+
29
+ private def access_modifier?: (AST::Declarations::t | AST::Members::t?) -> bool
30
+
27
31
  private def update_decl: (decl_with_members, members: Array[AST::Declarations::t | AST::Members::t]) -> decl_with_members
28
32
 
29
33
  private def absolute_typename: (TypeName, context: Resolver::context) -> TypeName
@@ -796,7 +796,7 @@ class Logger
796
796
  # periodic log file rotation; default is `'%Y%m%d'`. See [Periodic
797
797
  # Rotation](rdoc-ref:Logger@Periodic+Rotation).
798
798
  #
799
- def initialize: (logdev logdev, ?Numeric | String shift_age, ?Integer shift_size, ?shift_period_suffix: String, ?binmode: boolish, ?datetime_format: String, ?formatter: _Formatter, ?progname: String, ?level: Integer | String | Symbol) -> void
799
+ def initialize: (logdev? logdev, ?Numeric | String shift_age, ?Integer shift_size, ?shift_period_suffix: String, ?binmode: boolish, ?datetime_format: String, ?formatter: _Formatter, ?progname: String, ?level: Integer | String | Symbol) -> void
800
800
  end
801
801
 
802
802
  Logger::ProgName: String
@@ -0,0 +1,219 @@
1
+ # <!-- rdoc-file=lib/observer.rb -->
2
+ # The Observer pattern (also known as publish/subscribe) provides a simple
3
+ # mechanism for one object to inform a set of interested third-party objects
4
+ # when its state changes.
5
+ #
6
+ # ## Mechanism
7
+ #
8
+ # The notifying class mixes in the `Observable` module, which provides the
9
+ # methods for managing the associated observer objects.
10
+ #
11
+ # The observable object must:
12
+ # * assert that it has `#changed`
13
+ # * call `#notify_observers`
14
+ #
15
+ #
16
+ # An observer subscribes to updates using Observable#add_observer, which also
17
+ # specifies the method called via #notify_observers. The default method for
18
+ # #notify_observers is #update.
19
+ #
20
+ # ### Example
21
+ #
22
+ # The following example demonstrates this nicely. A `Ticker`, when run,
23
+ # continually receives the stock `Price` for its `@symbol`. A `Warner` is a
24
+ # general observer of the price, and two warners are demonstrated, a `WarnLow`
25
+ # and a `WarnHigh`, which print a warning if the price is below or above their
26
+ # set limits, respectively.
27
+ #
28
+ # The `update` callback allows the warners to run without being explicitly
29
+ # called. The system is set up with the `Ticker` and several observers, and the
30
+ # observers do their duty without the top-level code having to interfere.
31
+ #
32
+ # Note that the contract between publisher and subscriber (observable and
33
+ # observer) is not declared or enforced. The `Ticker` publishes a time and a
34
+ # price, and the warners receive that. But if you don't ensure that your
35
+ # contracts are correct, nothing else can warn you.
36
+ #
37
+ # require "observer"
38
+ #
39
+ # class Ticker ### Periodically fetch a stock price.
40
+ # include Observable
41
+ #
42
+ # def initialize(symbol)
43
+ # @symbol = symbol
44
+ # end
45
+ #
46
+ # def run
47
+ # last_price = nil
48
+ # loop do
49
+ # price = Price.fetch(@symbol)
50
+ # print "Current price: #{price}\n"
51
+ # if price != last_price
52
+ # changed # notify observers
53
+ # last_price = price
54
+ # notify_observers(Time.now, price)
55
+ # end
56
+ # sleep 1
57
+ # end
58
+ # end
59
+ # end
60
+ #
61
+ # class Price ### A mock class to fetch a stock price (60 - 140).
62
+ # def self.fetch(symbol)
63
+ # 60 + rand(80)
64
+ # end
65
+ # end
66
+ #
67
+ # class Warner ### An abstract observer of Ticker objects.
68
+ # def initialize(ticker, limit)
69
+ # @limit = limit
70
+ # ticker.add_observer(self)
71
+ # end
72
+ # end
73
+ #
74
+ # class WarnLow < Warner
75
+ # def update(time, price) # callback for observer
76
+ # if price < @limit
77
+ # print "--- #{time.to_s}: Price below #@limit: #{price}\n"
78
+ # end
79
+ # end
80
+ # end
81
+ #
82
+ # class WarnHigh < Warner
83
+ # def update(time, price) # callback for observer
84
+ # if price > @limit
85
+ # print "+++ #{time.to_s}: Price above #@limit: #{price}\n"
86
+ # end
87
+ # end
88
+ # end
89
+ #
90
+ # ticker = Ticker.new("MSFT")
91
+ # WarnLow.new(ticker, 80)
92
+ # WarnHigh.new(ticker, 120)
93
+ # ticker.run
94
+ #
95
+ # Produces:
96
+ #
97
+ # Current price: 83
98
+ # Current price: 75
99
+ # --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75
100
+ # Current price: 90
101
+ # Current price: 134
102
+ # +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134
103
+ # Current price: 134
104
+ # Current price: 112
105
+ # Current price: 79
106
+ # --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
107
+ #
108
+ # ### Usage with procs
109
+ #
110
+ # The `#notify_observers` method can also be used with +proc+s by using the
111
+ # `:call` as `func` parameter.
112
+ #
113
+ # The following example illustrates the use of a lambda:
114
+ #
115
+ # require 'observer'
116
+ #
117
+ # class Ticker
118
+ # include Observable
119
+ #
120
+ # def run
121
+ # # logic to retrieve the price (here 77.0)
122
+ # changed
123
+ # notify_observers(77.0)
124
+ # end
125
+ # end
126
+ #
127
+ # ticker = Ticker.new
128
+ # warner = ->(price) { puts "New price received: #{price}" }
129
+ # ticker.add_observer(warner, :call)
130
+ # ticker.run
131
+ #
132
+ module Observable
133
+ public
134
+
135
+ # <!--
136
+ # rdoc-file=lib/observer.rb
137
+ # - add_observer(observer, func=:update)
138
+ # -->
139
+ # Add `observer` as an observer on this object. So that it will receive
140
+ # notifications.
141
+ #
142
+ # `observer`
143
+ # : the object that will be notified of changes.
144
+ # `func`
145
+ # : Symbol naming the method that will be called when this Observable has
146
+ # changes.
147
+ #
148
+ # This method must return true for `observer.respond_to?` and will receive
149
+ # `*arg` when #notify_observers is called, where `*arg` is the value passed
150
+ # to #notify_observers by this Observable
151
+ #
152
+ def add_observer: (untyped observer, ?Symbol func) -> void
153
+
154
+ # <!--
155
+ # rdoc-file=lib/observer.rb
156
+ # - changed(state=true)
157
+ # -->
158
+ # Set the changed state of this object. Notifications will be sent only if the
159
+ # changed `state` is `true`.
160
+ #
161
+ # `state`
162
+ # : Boolean indicating the changed state of this Observable.
163
+ #
164
+ def changed: (?bool state) -> void
165
+
166
+ # <!--
167
+ # rdoc-file=lib/observer.rb
168
+ # - changed?()
169
+ # -->
170
+ # Returns true if this object's state has been changed since the last
171
+ # #notify_observers call.
172
+ #
173
+ def changed?: () -> bool
174
+
175
+ # <!--
176
+ # rdoc-file=lib/observer.rb
177
+ # - count_observers()
178
+ # -->
179
+ # Return the number of observers associated with this object.
180
+ #
181
+ def count_observers: () -> Integer
182
+
183
+ # <!--
184
+ # rdoc-file=lib/observer.rb
185
+ # - delete_observer(observer)
186
+ # -->
187
+ # Remove `observer` as an observer on this object so that it will no longer
188
+ # receive notifications.
189
+ #
190
+ # `observer`
191
+ # : An observer of this Observable
192
+ #
193
+ def delete_observer: (untyped observer) -> void
194
+
195
+ # <!--
196
+ # rdoc-file=lib/observer.rb
197
+ # - delete_observers()
198
+ # -->
199
+ # Remove all observers associated with this object.
200
+ #
201
+ def delete_observers: () -> void
202
+
203
+ # <!--
204
+ # rdoc-file=lib/observer.rb
205
+ # - notify_observers(*arg)
206
+ # -->
207
+ # Notify observers of a change in state **if** this object's changed state is
208
+ # `true`.
209
+ #
210
+ # This will invoke the method named in #add_observer, passing `*arg`. The
211
+ # changed state is then set to `false`.
212
+ #
213
+ # `*arg`
214
+ # : Any arguments to pass to the observers.
215
+ #
216
+ def notify_observers: (*untyped arg) -> void
217
+
218
+ VERSION: String
219
+ end
@@ -1,3 +1,27 @@
1
+ # <!-- rdoc-file=lib/uri/common.rb -->
2
+ # Base class for all URI exceptions.
3
+ #
4
+ class URI::Error < StandardError
5
+ end
6
+
7
+ # <!-- rdoc-file=lib/uri/common.rb -->
8
+ # Not a URI.
9
+ #
10
+ class URI::InvalidURIError < URI::Error
11
+ end
12
+
13
+ # <!-- rdoc-file=lib/uri/common.rb -->
14
+ # Not a URI component.
15
+ #
16
+ class URI::InvalidComponentError < URI::Error
17
+ end
18
+
19
+ # <!-- rdoc-file=lib/uri/common.rb -->
20
+ # URI is valid, bad usage is not.
21
+ #
22
+ class URI::BadURIError < URI::Error
23
+ end
24
+
1
25
  # <!-- rdoc-file=lib/uri.rb -->
2
26
  # URI is a module providing classes to handle Uniform Resource Identifiers
3
27
  # ([RFC2396](http://tools.ietf.org/html/rfc2396)).