sorbet-runtime 0.5.5267 → 0.5.5278

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e80e62f05cff1ad901687fffed408a7f499960c8f6f1eb385e1c718da5c22f5
4
- data.tar.gz: 4f3a1278a70cf33a7b089169822f8f112fab2f9fb4163971259fd2706e6a83c5
3
+ metadata.gz: 351ff337a29d85d7adcd563eb352cc9516be5d80ac8d4c7eda271e51ed295d52
4
+ data.tar.gz: 2d1f3e87d3b84650f4bcf3ca1eae08385999e1c9e9cbe930cb42db7289c9497d
5
5
  SHA512:
6
- metadata.gz: 299a7722c03ca6ad39c8f6ef613baeee4cbe5dc5876d603de8735dc68ef9f4c4cd172b33e6ef8f4a5a6aa31ec344536c6b3da7d017573270e5d14fd7c59a8e1f
7
- data.tar.gz: c344d7b552ea719a41e76e01aab817910442cf80a78dcac81aa5c0037365212bed2d06fedbb412252076812170f983b3763dfd6e3b99d0bf746187f76f8f88dc
6
+ metadata.gz: ece19477f2ce3df3d12a314a90eeed696b4168ddae9fd78e052d3f60a21c6bb618aeda3db95fd30e5947369f6bf04be07f8856b4781259d9693d157128f219eb
7
+ data.tar.gz: fa6c021527b7d372c4f648103245117c6b2998ffd7bb63ada0dc6216d3ae6dfd077c53a4659132c6d38aec6b3b3415eabfd49f81055f6dd06dce821b9da15f91
@@ -51,8 +51,14 @@ class T::Private::Methods::Signature
51
51
  @on_failure = on_failure
52
52
  @override_allow_incompatible = override_allow_incompatible
53
53
 
54
- param_names = parameters.map {|_, name| name}
55
54
  declared_param_names = raw_arg_types.keys
55
+ # If sig params are declared but there is a single parameter with a missing name
56
+ # **and** the method ends with a "=", assume it is a writer method generated
57
+ # by attr_writer or attr_accessor
58
+ writer_method = declared_param_names != [nil] && parameters == [[:req]] && method_name[-1] == "="
59
+ # For writer methods, map the single parameter to the method name without the "=" at the end
60
+ parameters = [[:req, method_name[0...-1].to_sym]] if writer_method
61
+ param_names = parameters.map {|_, name| name}
56
62
  missing_names = param_names - declared_param_names
57
63
  extra_names = declared_param_names - param_names
58
64
  if !missing_names.empty?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: false
2
+ # typed: strict
3
3
 
4
4
  # NB: This is not actually a decorator. It's just named that way for consistency
5
5
  # with DocumentDecorator and ModelDecorator (which both seem to have been written
@@ -11,26 +11,27 @@ class T::Props::Decorator
11
11
  extend T::Sig
12
12
 
13
13
  Rules = T.type_alias {T::Hash[Symbol, T.untyped]}
14
- DecoratedClass = T.type_alias {T.untyped} # T.class_of(T::Props), but that produces circular reference errors in some circumstances
15
- DecoratedInstance = T.type_alias {T.untyped} # Would be T::Props, but that produces circular reference errors in some circumstances
14
+ DecoratedInstance = T.type_alias {Object} # Would be T::Props, but that produces circular reference errors in some circumstances
16
15
  PropType = T.type_alias {T.any(T::Types::Base, T::Props::CustomType)}
17
16
  PropTypeOrClass = T.type_alias {T.any(PropType, Module)}
18
17
 
19
18
  class NoRulesError < StandardError; end
20
19
 
21
- sig {params(klass: DecoratedClass).void.checked(:never)}
20
+ EMPTY_PROPS = T.let({}.freeze, T::Hash[Symbol, Rules])
21
+ private_constant :EMPTY_PROPS
22
+
23
+ sig {params(klass: T.untyped).void}
22
24
  def initialize(klass)
23
- @class = klass
24
- klass.plugins.each do |mod|
25
- Private.apply_decorator_methods(mod, self)
25
+ @class = T.let(klass, T.all(Module, T::Props::ClassMethods))
26
+ @class.plugins.each do |mod|
27
+ T::Props::Plugin::Private.apply_decorator_methods(mod, self)
26
28
  end
29
+ @props = T.let(EMPTY_PROPS, T::Hash[Symbol, Rules])
27
30
  end
28
31
 
29
32
  # checked(:never) - O(prop accesses)
30
33
  sig {returns(T::Hash[Symbol, Rules]).checked(:never)}
31
- def props
32
- @props ||= {}.freeze
33
- end
34
+ attr_reader :props
34
35
 
35
36
  # Try to avoid using this; post-definition mutation of prop rules is
36
37
  # surprising and hard to reason about.
@@ -62,7 +63,7 @@ class T::Props::Decorator
62
63
  @props = @props.merge(prop => rules.freeze).freeze
63
64
  end
64
65
 
65
- VALID_RULE_KEYS = %i{
66
+ VALID_RULE_KEYS = T.let(%i{
66
67
  enum
67
68
  foreign
68
69
  foreign_hint_only
@@ -76,16 +77,16 @@ class T::Props::Decorator
76
77
  extra
77
78
  optional
78
79
  _tnilable
79
- }.map {|k| [k, true]}.to_h.freeze
80
+ }.map {|k| [k, true]}.to_h.freeze, T::Hash[Symbol, T::Boolean])
80
81
  private_constant :VALID_RULE_KEYS
81
82
 
82
83
  sig {params(key: Symbol).returns(T::Boolean).checked(:never)}
83
84
  def valid_rule_key?(key)
84
- VALID_RULE_KEYS[key]
85
+ !!VALID_RULE_KEYS[key]
85
86
  end
86
87
 
87
88
  # checked(:never) - O(prop accesses)
88
- sig {returns(DecoratedClass).checked(:never)}
89
+ sig {returns(T.all(Module, T::Props::ClassMethods)).checked(:never)}
89
90
  def decorated_class; @class; end
90
91
 
91
92
  # Accessors
@@ -135,13 +136,13 @@ class T::Props::Decorator
135
136
  instance: DecoratedInstance,
136
137
  prop: Symbol,
137
138
  val: T.untyped,
138
- rules: T.nilable(Rules)
139
+ rules: Rules
139
140
  )
140
141
  .void
141
142
  .checked(:never)
142
143
  end
143
144
  def prop_set(instance, prop, val, rules=prop_rules(prop))
144
- instance.instance_exec(val, &rules[:setter_proc])
145
+ instance.instance_exec(val, &rules.fetch(:setter_proc))
145
146
  end
146
147
  alias_method :set, :prop_set
147
148
 
@@ -184,18 +185,18 @@ class T::Props::Decorator
184
185
  prop: Symbol,
185
186
  foreign_class: Module,
186
187
  rules: Rules,
187
- opts: Hash
188
+ opts: T::Hash[Symbol, T.untyped],
188
189
  )
189
190
  .returns(T.untyped)
190
191
  .checked(:never)
191
192
  end
192
193
  def foreign_prop_get(instance, prop, foreign_class, rules=props[prop.to_sym], opts={})
193
194
  return if !(value = prop_get(instance, prop, rules))
194
- foreign_class.load(value, {}, opts)
195
+ T.unsafe(foreign_class).load(value, {}, opts)
195
196
  end
196
197
 
197
198
  # TODO: we should really be checking all the methods on `cls`, not just Object
198
- BANNED_METHOD_NAMES = Object.instance_methods.to_set.freeze
199
+ BANNED_METHOD_NAMES = T.let(Object.instance_methods.to_set.freeze, T::Set[Symbol])
199
200
 
200
201
  # checked(:never) - Rules hash is expensive to check
201
202
  sig do
@@ -245,6 +246,7 @@ class T::Props::Decorator
245
246
  nil
246
247
  end
247
248
 
249
+ sig {params(name: Symbol).void}
248
250
  private def validate_prop_name(name)
249
251
  if name !~ /\A[A-Za-z_][A-Za-z0-9_-]*\z/
250
252
  raise ArgumentError.new("Invalid prop name in #{@class.name}: #{name}")
@@ -371,7 +373,7 @@ class T::Props::Decorator
371
373
  # are ultimately included does.
372
374
  #
373
375
  if defined?(Opus) && defined?(Opus::Sensitivity) && defined?(Opus::Sensitivity::PIIable)
374
- if sensitivity_and_pii[:pii] && @class.is_a?(Class) && !@class.contains_pii?
376
+ if sensitivity_and_pii[:pii] && @class.is_a?(Class) && !T.unsafe(@class).contains_pii?
375
377
  raise ArgumentError.new(
376
378
  'Cannot include a pii prop in a class that declares `contains_no_pii`'
377
379
  )
@@ -454,21 +456,21 @@ class T::Props::Decorator
454
456
  if !rules[:immutable]
455
457
  if method(:prop_set).owner != T::Props::Decorator
456
458
  @class.send(:define_method, "#{name}=") do |val|
457
- self.class.decorator.prop_set(self, name, val, rules)
459
+ T.unsafe(self.class).decorator.prop_set(self, name, val, rules)
458
460
  end
459
461
  else
460
462
  # Fast path (~4x faster as of Ruby 2.6)
461
- @class.send(:define_method, "#{name}=", &rules[:setter_proc])
463
+ @class.send(:define_method, "#{name}=", &rules.fetch(:setter_proc))
462
464
  end
463
465
  end
464
466
 
465
467
  if method(:prop_get).owner != T::Props::Decorator || rules.key?(:ifunset)
466
468
  @class.send(:define_method, name) do
467
- self.class.decorator.prop_get(self, name, rules)
469
+ T.unsafe(self.class).decorator.prop_get(self, name, rules)
468
470
  end
469
471
  else
470
472
  # Fast path (~30x faster as of Ruby 2.6)
471
- @class.attr_reader(name)
473
+ @class.send(:attr_reader, name) # send is used because `attr_reader` is private in 2.4
472
474
  end
473
475
  end
474
476
  end
@@ -536,10 +538,10 @@ class T::Props::Decorator
536
538
  end
537
539
 
538
540
  # From T::Props::Utils.deep_clone_object, plus String
539
- TYPES_NOT_NEEDING_CLONE = [TrueClass, FalseClass, NilClass, Symbol, String, Numeric]
541
+ TYPES_NOT_NEEDING_CLONE = T.let([TrueClass, FalseClass, NilClass, Symbol, String, Numeric], T::Array[Module])
540
542
 
541
543
  # checked(:never) - Typechecks internally
542
- sig {params(type: PropType).returns(T::Boolean).checked(:never)}
544
+ sig {params(type: PropType).returns(T.nilable(T::Boolean)).checked(:never)}
543
545
  private def shallow_clone_ok(type)
544
546
  inner_type =
545
547
  if type.is_a?(T::Types::TypedArray)
@@ -581,7 +583,7 @@ class T::Props::Decorator
581
583
  end
582
584
 
583
585
  # checked(:never) - Rules hash is expensive to check
584
- sig {params(prop_name: Symbol, rules: Hash).void.checked(:never)}
586
+ sig {params(prop_name: Symbol, rules: Rules).void.checked(:never)}
585
587
  private def validate_not_missing_sensitivity(prop_name, rules)
586
588
  if rules[:sensitivity].nil?
587
589
  if rules[:redaction]
@@ -686,6 +688,7 @@ class T::Props::Decorator
686
688
  # *haven't* allowed additional options in the past and want to
687
689
  # default to keeping this interface narrow.
688
690
  @class.send(:define_method, fk_method) do |allow_direct_mutation: nil|
691
+ foreign = T.let(foreign, T.untyped)
689
692
  if foreign.is_a?(Proc)
690
693
  resolved_foreign = foreign.call
691
694
  if !resolved_foreign.respond_to?(:load)
@@ -704,7 +707,7 @@ class T::Props::Decorator
704
707
  opts = {allow_direct_mutation: allow_direct_mutation}
705
708
  end
706
709
 
707
- self.class.decorator.foreign_prop_get(self, prop_name, foreign, rules, opts)
710
+ T.unsafe(self.class).decorator.foreign_prop_get(self, prop_name, foreign, rules, opts)
708
711
  end
709
712
 
710
713
  force_fk_method = "#{fk_method}!"
@@ -716,7 +719,7 @@ class T::Props::Decorator
716
719
  storytime: {method: force_fk_method, class: self.class}
717
720
  )
718
721
  end
719
- T.must(loaded_foreign)
722
+ loaded_foreign
720
723
  end
721
724
 
722
725
  @class.send(:define_method, "#{prop_name}_record") do |allow_direct_mutation: nil|
@@ -765,16 +768,17 @@ class T::Props::Decorator
765
768
  #
766
769
  # This gets called when a module or class that extends T::Props gets included, extended,
767
770
  # prepended, or inherited.
768
- sig {params(child: DecoratedClass).void.checked(:never)}
771
+ sig {params(child: Module).void.checked(:never)}
769
772
  def model_inherited(child)
770
773
  child.extend(T::Props::ClassMethods)
771
- child.plugins.concat(decorated_class.plugins)
774
+ child = T.cast(child, T.all(Module, T::Props::ClassMethods))
772
775
 
776
+ child.plugins.concat(decorated_class.plugins)
773
777
  decorated_class.plugins.each do |mod|
774
778
  # NB: apply_class_methods must not be an instance method on the decorator itself,
775
779
  # otherwise we'd have to call child.decorator here, which would create the decorator
776
780
  # before any `decorator_class` override has a chance to take effect (see the comment below).
777
- Private.apply_class_methods(mod, child)
781
+ T::Props::Plugin::Private.apply_class_methods(mod, child)
778
782
  end
779
783
 
780
784
  props.each do |name, rules|
@@ -794,17 +798,17 @@ class T::Props::Decorator
794
798
  #
795
799
  unless rules[:without_accessors]
796
800
  if child.decorator.method(:prop_get).owner != method(:prop_get).owner &&
797
- child.instance_method(name).source_location.first == __FILE__
801
+ child.instance_method(name).source_location&.first == __FILE__
798
802
  child.send(:define_method, name) do
799
- self.class.decorator.prop_get(self, name, rules)
803
+ T.unsafe(self.class).decorator.prop_get(self, name, rules)
800
804
  end
801
805
  end
802
806
 
803
807
  unless rules[:immutable]
804
808
  if child.decorator.method(:prop_set).owner != method(:prop_set).owner &&
805
- child.instance_method("#{name}=").source_location.first == __FILE__
809
+ child.instance_method("#{name}=").source_location&.first == __FILE__
806
810
  child.send(:define_method, "#{name}=") do |val|
807
- self.class.decorator.prop_set(self, name, val, rules)
811
+ T.unsafe(self.class).decorator.prop_set(self, name, val, rules)
808
812
  end
809
813
  end
810
814
  end
@@ -815,27 +819,7 @@ class T::Props::Decorator
815
819
  sig {params(mod: Module).void.checked(:never)}
816
820
  def plugin(mod)
817
821
  decorated_class.plugins << mod
818
- Private.apply_class_methods(mod, decorated_class)
819
- Private.apply_decorator_methods(mod, self)
820
- end
821
-
822
- module Private
823
- # These need to be non-instance methods so we can use them without prematurely creating the
824
- # child decorator in `model_inherited` (see comments there for details).
825
- def self.apply_class_methods(plugin, target)
826
- if plugin.const_defined?('ClassMethods')
827
- # FIXME: This will break preloading, selective test execution, etc if `mod::ClassMethods`
828
- # is ever defined in a separate file from `mod`.
829
- target.extend(plugin::ClassMethods) # rubocop:disable PrisonGuard/NoDynamicConstAccess
830
- end
831
- end
832
-
833
- def self.apply_decorator_methods(plugin, target)
834
- if plugin.const_defined?('DecoratorMethods')
835
- # FIXME: This will break preloading, selective test execution, etc if `mod::DecoratorMethods`
836
- # is ever defined in a separate file from `mod`.
837
- target.extend(plugin::DecoratorMethods) # rubocop:disable PrisonGuard/NoDynamicConstAccess
838
- end
839
- end
822
+ T::Props::Plugin::Private.apply_class_methods(mod, decorated_class)
823
+ T::Props::Plugin::Private.apply_decorator_methods(mod, self)
840
824
  end
841
825
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: true
2
+ # typed: false
3
3
 
4
4
  module T::Props::Plugin
5
5
  include T::Props
@@ -12,4 +12,26 @@ module T::Props::Plugin
12
12
  end
13
13
  end
14
14
  mixes_in_class_methods(ClassMethods)
15
+
16
+ module Private
17
+ # These need to be non-instance methods so we can use them without prematurely creating the
18
+ # child decorator in `model_inherited` (see comments there for details).
19
+ #
20
+ # The dynamic constant access below forces this file to be `typed: false`
21
+ def self.apply_class_methods(plugin, target)
22
+ if plugin.const_defined?('ClassMethods')
23
+ # FIXME: This will break preloading, selective test execution, etc if `mod::ClassMethods`
24
+ # is ever defined in a separate file from `mod`.
25
+ target.extend(plugin::ClassMethods) # rubocop:disable PrisonGuard/NoDynamicConstAccess
26
+ end
27
+ end
28
+
29
+ def self.apply_decorator_methods(plugin, target)
30
+ if plugin.const_defined?('DecoratorMethods')
31
+ # FIXME: This will break preloading, selective test execution, etc if `mod::DecoratorMethods`
32
+ # is ever defined in a separate file from `mod`.
33
+ target.extend(plugin::DecoratorMethods) # rubocop:disable PrisonGuard/NoDynamicConstAccess
34
+ end
35
+ end
36
+ end
15
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5267
4
+ version: 0.5.5278
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-22 00:00:00.000000000 Z
11
+ date: 2020-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest