rbs 3.1.3 → 3.2.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +0 -6
- data/CHANGELOG.md +68 -0
- data/Gemfile +0 -6
- data/Gemfile.lock +12 -21
- data/README.md +1 -1
- data/Rakefile +44 -0
- data/Steepfile +3 -3
- data/core/array.rbs +0 -8
- data/core/builtin.rbs +28 -8
- data/core/constants.rbs +13 -5
- data/core/exception.rbs +1 -1
- data/core/global_variables.rbs +27 -27
- data/core/io.rbs +163 -172
- data/core/kernel.rbs +7 -4
- data/core/module.rbs +34 -32
- data/core/object.rbs +2 -2
- data/core/string_io.rbs +9 -0
- data/core/thread.rbs +25 -1
- data/core/time.rbs +3 -3
- data/docs/CONTRIBUTING.md +1 -1
- data/docs/rbs_by_example.md +16 -35
- data/docs/repo.md +1 -1
- data/docs/sigs.md +7 -7
- data/docs/stdlib.md +2 -3
- data/docs/syntax.md +40 -40
- data/lib/rbs/cli.rb +15 -4
- data/lib/rbs/collection/installer.rb +5 -2
- data/lib/rbs/collection/sources/stdlib.rb +5 -1
- data/lib/rbs/errors.rb +8 -1
- data/lib/rbs/file_finder.rb +1 -1
- data/lib/rbs/prototype/rb.rb +64 -6
- data/lib/rbs/prototype/rbi.rb +2 -6
- data/lib/rbs/prototype/runtime.rb +29 -8
- data/lib/rbs/subtractor.rb +17 -0
- data/lib/rbs/type_name.rb +4 -4
- data/lib/rbs/version.rb +1 -1
- data/rbs.gemspec +1 -1
- data/schema/decls.json +1 -1
- data/sig/errors.rbs +54 -0
- data/sig/parser.rbs +2 -2
- data/sig/prototype/rb.rbs +9 -1
- data/sig/subtractor.rbs +4 -0
- data/stdlib/logger/0/logger.rbs +1 -1
- data/stdlib/observable/0/observable.rbs +219 -0
- data/stdlib/uri/0/common.rbs +24 -0
- data/stdlib/zlib/0/buf_error.rbs +79 -0
- data/stdlib/zlib/0/data_error.rbs +79 -0
- data/stdlib/zlib/0/deflate.rbs +276 -0
- data/stdlib/zlib/0/error.rbs +89 -0
- data/stdlib/zlib/0/gzip_file/crc_error.rbs +115 -0
- data/stdlib/zlib/0/gzip_file/error.rbs +128 -0
- data/stdlib/zlib/0/gzip_file/length_error.rbs +115 -0
- data/stdlib/zlib/0/gzip_file/no_footer.rbs +114 -0
- data/stdlib/zlib/0/gzip_file.rbs +228 -0
- data/stdlib/zlib/0/gzip_reader.rbs +362 -0
- data/stdlib/zlib/0/gzip_writer.rbs +237 -0
- data/stdlib/zlib/0/inflate.rbs +249 -0
- data/stdlib/zlib/0/mem_error.rbs +79 -0
- data/stdlib/zlib/0/need_dict.rbs +82 -0
- data/stdlib/zlib/0/stream_end.rbs +80 -0
- data/stdlib/zlib/0/stream_error.rbs +80 -0
- data/stdlib/zlib/0/version_error.rbs +80 -0
- data/stdlib/zlib/0/zstream.rbs +270 -0
- metadata +24 -8
- data/stdlib/prime/0/integer-extension.rbs +0 -41
- data/stdlib/prime/0/manifest.yaml +0 -2
- 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
|
|
data/lib/rbs/subtractor.rb
CHANGED
@@ -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
|
13
|
-
when
|
12
|
+
@kind = case
|
13
|
+
when name.match?(/\A[A-Z]/)
|
14
14
|
:class
|
15
|
-
when
|
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
data/rbs.gemspec
CHANGED
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:
|
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 `
|
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 `
|
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
|
-
|
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
|
data/stdlib/logger/0/logger.rbs
CHANGED
@@ -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
|
data/stdlib/uri/0/common.rbs
CHANGED
@@ -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)).
|