smart_initializer 0.1.0.alpha4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +36 -5
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile.lock +48 -31
  6. data/README.md +151 -22
  7. data/Rakefile +1 -1
  8. data/bin/rspec +54 -0
  9. data/gemfiles/with_external_deps.gemfile +7 -0
  10. data/gemfiles/with_external_deps.gemfile.lock +99 -0
  11. data/gemfiles/without_external_deps.gemfile +5 -0
  12. data/gemfiles/without_external_deps.gemfile.lock +97 -0
  13. data/lib/smart_core/initializer.rb +38 -35
  14. data/lib/smart_core/initializer/attribute.rb +12 -4
  15. data/lib/smart_core/initializer/attribute/factory.rb +47 -27
  16. data/lib/smart_core/initializer/attribute/parameters.rb +12 -4
  17. data/lib/smart_core/initializer/configurable_module.rb +27 -0
  18. data/lib/smart_core/initializer/configuration.rb +33 -0
  19. data/lib/smart_core/initializer/constructor.rb +9 -6
  20. data/lib/smart_core/initializer/constructor/definer.rb +34 -11
  21. data/lib/smart_core/initializer/dsl.rb +23 -6
  22. data/lib/smart_core/initializer/errors.rb +44 -0
  23. data/lib/smart_core/initializer/plugins.rb +17 -0
  24. data/lib/smart_core/initializer/plugins/abstract.rb +55 -0
  25. data/lib/smart_core/initializer/plugins/access_mixin.rb +47 -0
  26. data/lib/smart_core/initializer/plugins/registry.rb +166 -0
  27. data/lib/smart_core/initializer/plugins/registry_interface.rb +77 -0
  28. data/lib/smart_core/initializer/plugins/thy_types.rb +30 -0
  29. data/lib/smart_core/initializer/plugins/thy_types/errors.rb +11 -0
  30. data/lib/smart_core/initializer/plugins/thy_types/thy_types.rb +23 -0
  31. data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +78 -0
  32. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation.rb +12 -0
  33. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/base.rb +9 -0
  34. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/cast.rb +21 -0
  35. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/valid.rb +16 -0
  36. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/validate.rb +19 -0
  37. data/lib/smart_core/initializer/settings.rb +49 -0
  38. data/lib/smart_core/initializer/settings/duplicator.rb +20 -0
  39. data/lib/smart_core/initializer/settings/type_system.rb +69 -0
  40. data/lib/smart_core/initializer/type_system.rb +16 -0
  41. data/lib/smart_core/initializer/type_system/interop.rb +103 -0
  42. data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +70 -0
  43. data/lib/smart_core/initializer/type_system/interop/aliasing.rb +72 -0
  44. data/lib/smart_core/initializer/type_system/interop/aliasing/alias_list.rb +141 -0
  45. data/lib/smart_core/initializer/type_system/interop/operation.rb +30 -0
  46. data/lib/smart_core/initializer/type_system/registry.rb +174 -0
  47. data/lib/smart_core/initializer/type_system/registry_interface.rb +102 -0
  48. data/lib/smart_core/initializer/type_system/smart_types.rb +48 -0
  49. data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +72 -0
  50. data/lib/smart_core/initializer/type_system/smart_types/operation.rb +13 -0
  51. data/lib/smart_core/initializer/type_system/smart_types/operation/base.rb +8 -0
  52. data/lib/smart_core/initializer/type_system/smart_types/operation/cast.rb +16 -0
  53. data/lib/smart_core/initializer/type_system/smart_types/operation/valid.rb +16 -0
  54. data/lib/smart_core/initializer/type_system/smart_types/operation/validate.rb +16 -0
  55. data/lib/smart_core/initializer/version.rb +1 -1
  56. data/smart_initializer.gemspec +13 -9
  57. metadata +67 -17
  58. data/lib/smart_core/initializer/attribute/init_extension.rb +0 -4
  59. data/lib/smart_core/initializer/type_aliasing.rb +0 -50
  60. data/lib/smart_core/initializer/type_aliasing/alias_list.rb +0 -101
@@ -43,12 +43,18 @@ class SmartCore::Initializer::Attribute::Parameters
43
43
  # @since 0.1.0
44
44
  attr_reader :name
45
45
 
46
- # @return [SmartCore::Types::Primitive]
46
+ # @return [SmartCore::Initializer::TypeSystem::Interop]
47
47
  #
48
48
  # @api private
49
49
  # @since 0.1.0
50
50
  attr_reader :type
51
51
 
52
+ # @return [Class<SmartCore::Initilizer::TypeSystem::Interop>]
53
+ #
54
+ # @api private
55
+ # @since 0.1.0
56
+ attr_reader :type_system
57
+
52
58
  # @return [Symbol]
53
59
  #
54
60
  # @api private
@@ -76,7 +82,8 @@ class SmartCore::Initializer::Attribute::Parameters
76
82
  attr_reader :dynamic_options
77
83
 
78
84
  # @param name [Symbol]
79
- # @param type [SmartCore::Types::Primitive]
85
+ # @param type [SmartCore::Initializer::TypeSystem::Interop]
86
+ # @param type_system [Class<SmartCore::Initializer::TypeSystem::Interop>]
80
87
  # @param privacy [Symbol]
81
88
  # @param finalizer [SmartCore::Initializer::Attribute::AnonymousBlock/InstanceMethod]
82
89
  # @param cast [Boolean]
@@ -86,9 +93,10 @@ class SmartCore::Initializer::Attribute::Parameters
86
93
  #
87
94
  # @api private
88
95
  # @since 0.1.0
89
- def initialize(name, type, privacy, finalizer, cast, dynamic_options)
96
+ def initialize(name, type, type_system, privacy, finalizer, cast, dynamic_options)
90
97
  @name = name
91
98
  @type = type
99
+ @type_system = type_system
92
100
  @privacy = privacy
93
101
  @finalizer = finalizer
94
102
  @cast = cast
@@ -116,6 +124,6 @@ class SmartCore::Initializer::Attribute::Parameters
116
124
  ERROR_MESSAGE
117
125
  end
118
126
 
119
- defalut_value.is_a?(Proc) ? default_value.call : default_value
127
+ default_value.is_a?(Proc) ? default_value.call : default_value
120
128
  end
121
129
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::ConfigurableModule
6
+ # @return [NilClass]
7
+ #
8
+ # @api private
9
+ # @since 0.1.0
10
+ INITIAL_TYPE_SYSTEM = nil
11
+
12
+ class << self
13
+ # @param type_system [String, Symbol, NilClass]
14
+ # @return [Module]
15
+ #
16
+ # @api private
17
+ # @since 0.1.0
18
+ def build(type_system: INITIAL_TYPE_SYSTEM)
19
+ Module.new.tap do |extension|
20
+ extension.singleton_class.define_method(:included) do |base_klass|
21
+ base_klass.include(::SmartCore::Initializer)
22
+ base_klass.__initializer_settings__.type_system = type_system
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'qonfig'
4
+
5
+ # @api public
6
+ # @since 0.1.0
7
+ module SmartCore::Initializer::Configuration
8
+ # @since 0.1.0
9
+ include Qonfig::Configurable
10
+
11
+ # @api public
12
+ # @since 0.1.0
13
+ extend SmartCore::Initializer::Plugins::AccessMixin
14
+
15
+ class << self
16
+ # @param setting_key [String, Symbol]
17
+ # @return [Qonfig::Settings, Any]
18
+ #
19
+ # @api private
20
+ # @since 0.1.0
21
+ def [](setting_key)
22
+ config[setting_key]
23
+ end
24
+ end
25
+
26
+ # @since 0.1.0
27
+ configuration do
28
+ setting :default_type_system, :smart_types
29
+ validate :default_type_system do |value|
30
+ SmartCore::Initializer::TypeSystem.resolve(value) rescue false
31
+ end
32
+ end
33
+ end
@@ -107,10 +107,10 @@ class SmartCore::Initializer::Constructor
107
107
  parameter_definitions = Hash[klass.__params__.zip(parameters)]
108
108
 
109
109
  parameter_definitions.each_pair do |attribute, parameter_value|
110
- parameter_value = attribute.type.cast(parameter_value) if attribute.cast?
110
+ if !attribute.type.valid?(parameter_value) && attribute.cast?
111
+ parameter_value = attribute.type.cast(parameter_value)
112
+ end
111
113
 
112
- # TODO: fail with SmartCore::Initializer::ArgumentError
113
- # (isntead of SmartCore::Types::TypeError)
114
114
  attribute.type.validate!(parameter_value)
115
115
 
116
116
  final_value = attribute.finalizer.call(parameter_value, instance)
@@ -123,19 +123,22 @@ class SmartCore::Initializer::Constructor
123
123
  #
124
124
  # @api private
125
125
  # @since 0.1.0
126
+ # rubocop:disable Metrics/AbcSize
126
127
  def initialize_options(instance)
127
128
  klass.__options__.each do |attribute|
128
129
  option_value = options.fetch(attribute.name) { attribute.default }
129
- option_value = attribute.type.cast(option_value) if attribute.cast?
130
130
 
131
- # TODO: fail with SmartCore::Initializer::ArgumentError
132
- # (isntead of SmartCore::Types::TypeError)
131
+ if !attribute.type.valid?(option_value) && attribute.cast?
132
+ option_value = attribute.type.cast(option_value)
133
+ end
134
+
133
135
  attribute.type.validate!(option_value)
134
136
 
135
137
  final_value = attribute.finalizer.call(option_value, instance)
136
138
  instance.instance_variable_set("@#{attribute.name}", final_value)
137
139
  end
138
140
  end
141
+ # rubocop:enable Metrics/AbcSize
139
142
 
140
143
  # @param instance [Any]
141
144
  # @return [void]
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # rubocop:disable Metrics/ClassLength
5
6
  class SmartCore::Initializer::Constructor::Definer
6
7
  # @param klass [Class]
7
8
  # @return [void]
@@ -25,7 +26,8 @@ class SmartCore::Initializer::Constructor::Definer
25
26
  end
26
27
 
27
28
  # @param name [String, Symbol]
28
- # @param type [String, Symbol, SmartCore::Types::Primitive]
29
+ # @param type [String, Symbol, Any]
30
+ # @param type_system [String, Symbol]
29
31
  # @param privacy [String, Symbol]
30
32
  # @param finalize [String, Symbol, Proc]
31
33
  # @param cast [Boolean]
@@ -34,9 +36,17 @@ class SmartCore::Initializer::Constructor::Definer
34
36
  #
35
37
  # @api private
36
38
  # @since 0.1.0
37
- def define_parameter(name, type, privacy, finalize, cast, dynamic_options)
39
+ def define_parameter(name, type, type_system, privacy, finalize, cast, dynamic_options)
38
40
  thread_safe do
39
- attribute = build_attribute(name, type, privacy, finalize, cast, dynamic_options)
41
+ attribute = build_attribute(
42
+ name,
43
+ type,
44
+ type_system,
45
+ privacy,
46
+ finalize,
47
+ cast,
48
+ dynamic_options
49
+ )
40
50
  prevent_option_overlap(attribute)
41
51
  add_parameter(attribute)
42
52
  end
@@ -52,7 +62,8 @@ class SmartCore::Initializer::Constructor::Definer
52
62
  names.map do |name|
53
63
  build_attribute(
54
64
  name,
55
- SmartCore::Types::Value::Any,
65
+ klass.__initializer_settings__.generic_type_object,
66
+ klass.__initializer_settings__.type_system,
56
67
  SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
57
68
  SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
58
69
  SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
@@ -67,7 +78,8 @@ class SmartCore::Initializer::Constructor::Definer
67
78
  end
68
79
 
69
80
  # @param name [String, Symbol]
70
- # @param type [String, Symbol, SmartCore::Types::Primitive]
81
+ # @param type [String, Symbol, Any]
82
+ # @param type_system [String, Symbol]
71
83
  # @param privacy [String, Symbol]
72
84
  # @param finalize [String, Symbol, Proc]
73
85
  # @param cast [Boolean]
@@ -76,9 +88,17 @@ class SmartCore::Initializer::Constructor::Definer
76
88
  #
77
89
  # @api private
78
90
  # @since 0.1.0
79
- def define_option(name, type, privacy, finalize, cast, dynamic_options)
91
+ def define_option(name, type, type_system, privacy, finalize, cast, dynamic_options)
80
92
  thread_safe do
81
- attribute = build_attribute(name, type, privacy, finalize, cast, dynamic_options)
93
+ attribute = build_attribute(
94
+ name,
95
+ type,
96
+ type_system,
97
+ privacy,
98
+ finalize,
99
+ cast,
100
+ dynamic_options
101
+ )
82
102
  prevent_parameter_overlap(attribute)
83
103
  add_option(attribute)
84
104
  end
@@ -94,7 +114,8 @@ class SmartCore::Initializer::Constructor::Definer
94
114
  names.map do |name|
95
115
  build_attribute(
96
116
  name,
97
- SmartCore::Types::Value::Any,
117
+ klass.__initializer_settings__.generic_type_object,
118
+ klass.__initializer_settings__.type_system,
98
119
  SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
99
120
  SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
100
121
  SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
@@ -117,7 +138,8 @@ class SmartCore::Initializer::Constructor::Definer
117
138
  attr_reader :klass
118
139
 
119
140
  # @param name [String, Symbol]
120
- # @param type [String, Symbol, SmartCore::Types::Primitive]
141
+ # @param type [String, Symbol, Any]
142
+ # @param type_system [String, Symbol]
121
143
  # @param privacy [String, Symbol]
122
144
  # @param finalize [String, Symbol, Proc]
123
145
  # @param cast [Boolean]
@@ -126,9 +148,9 @@ class SmartCore::Initializer::Constructor::Definer
126
148
  #
127
149
  # @api private
128
150
  # @since 0.1.0
129
- def build_attribute(name, type, privacy, finalize, cast, dynamic_options)
151
+ def build_attribute(name, type, type_system, privacy, finalize, cast, dynamic_options)
130
152
  SmartCore::Initializer::Attribute::Factory.create(
131
- name, type, privacy, finalize, cast, dynamic_options
153
+ name, type, type_system, privacy, finalize, cast, dynamic_options
132
154
  )
133
155
  end
134
156
 
@@ -207,3 +229,4 @@ class SmartCore::Initializer::Constructor::Definer
207
229
  @lock.synchronize(&block)
208
230
  end
209
231
  end
232
+ # rubocop:enable Metrics/ClassLength
@@ -18,6 +18,7 @@ module SmartCore::Initializer::DSL
18
18
  instance_variable_set(:@__init_extensions__, SmartCore::Initializer::Extensions::List.new)
19
19
  instance_variable_set(:@__definer__, SmartCore::Initializer::Constructor::Definer.new(self))
20
20
  instance_variable_set(:@__deflock__, SmartCore::Engine::Lock.new)
21
+ instance_variable_set(:@__initializer_settings__, SmartCore::Initializer::Settings.new)
21
22
  end
22
23
  base_klass.extend(ClassMethods)
23
24
  base_klass.singleton_class.prepend(ClassInheritance)
@@ -39,6 +40,7 @@ module SmartCore::Initializer::DSL
39
40
  instance_variable_set(:@__init_extensions__, SmartCore::Initializer::Extensions::List.new)
40
41
  instance_variable_set(:@__definer__, SmartCore::Initializer::Constructor::Definer.new(self))
41
42
  instance_variable_set(:@__deflock__, SmartCore::Engine::Lock.new)
43
+ instance_variable_set(:@__initializer_settings__, __initializer_settings__.dup)
42
44
  end
43
45
  child_klass.extend(ClassMethods)
44
46
  SmartCore::Initializer::DSL::Inheritance.inherit(base: self, child: child_klass)
@@ -81,6 +83,14 @@ module SmartCore::Initializer::DSL
81
83
  @__definer__
82
84
  end
83
85
 
86
+ # @return [SmartCore::Initializer::Settings]
87
+ #
88
+ # @api private
89
+ # @since 0.1.0
90
+ def __initializer_settings__
91
+ @__initializer_settings__
92
+ end
93
+
84
94
  # @param arguments [Array]
85
95
  # @param block [Block]
86
96
  # @return [Any]
@@ -92,7 +102,7 @@ module SmartCore::Initializer::DSL
92
102
  end
93
103
 
94
104
  # @param name [String, Symbol]
95
- # @param type [String, Symbol, SmartCore::Types::Primitive]
105
+ # @param type [String, Symbol, Any]
96
106
  # @option cast [Boolean]
97
107
  # @option privacy [String, Symbol]
98
108
  # @option finalize [String, Symbol, Proc]
@@ -103,13 +113,16 @@ module SmartCore::Initializer::DSL
103
113
  # @since 0.1.0
104
114
  def param(
105
115
  name,
106
- type = SmartCore::Types::Value::Any,
116
+ type = __initializer_settings__.generic_type_object,
107
117
  privacy: SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
108
118
  finalize: SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
109
119
  cast: SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
120
+ type_system: __initializer_settings__.type_system,
110
121
  **dynamic_options
111
122
  )
112
- __definer__.define_parameter(name, type, privacy, finalize, cast, dynamic_options)
123
+ __definer__.define_parameter(
124
+ name, type, type_system, privacy, finalize, cast, dynamic_options
125
+ )
113
126
  end
114
127
 
115
128
  # @param names [Array<String, Symbol>]
@@ -122,10 +135,11 @@ module SmartCore::Initializer::DSL
122
135
  end
123
136
 
124
137
  # @param name [String, Symbol]
125
- # @param type [String, Symbol, SmartCore::Types::Primitive]
138
+ # @param type [String, Symbol, Any]
126
139
  # @option cast [Boolean]
127
140
  # @option privacy [String, Symbol]
128
141
  # @option finalize [String, Symbol, Proc]
142
+ # @option type_system [String, Symbol]
129
143
  # @param dynamic_options [Hash<Symbol,Any>]
130
144
  # @return [void]
131
145
  #
@@ -133,13 +147,16 @@ module SmartCore::Initializer::DSL
133
147
  # @since 0.1.0
134
148
  def option(
135
149
  name,
136
- type = SmartCore::Types::Value::Any,
150
+ type = __initializer_settings__.generic_type_object,
137
151
  privacy: SmartCore::Initializer::Attribute::Parameters::DEFAULT_PRIVACY_MODE,
138
152
  finalize: SmartCore::Initializer::Attribute::Parameters::DEFAULT_FINALIZER,
139
153
  cast: SmartCore::Initializer::Attribute::Parameters::DEFAULT_CAST_BEHAVIOUR,
154
+ type_system: __initializer_settings__.type_system,
140
155
  **dynamic_options
141
156
  )
142
- __definer__.define_option(name, type, privacy, finalize, cast, dynamic_options)
157
+ __definer__.define_option(
158
+ name, type, type_system, privacy, finalize, cast, dynamic_options
159
+ )
143
160
  end
144
161
 
145
162
  # @param names [Array<String, Symbol>]
@@ -32,4 +32,48 @@ module SmartCore::Initializer
32
32
  # @api public
33
33
  # @since 0.1.0
34
34
  NoTypeAliasError = Class.new(Error)
35
+
36
+ # @api public
37
+ # @since 0.1.0
38
+ PluginError = Class.new(Error)
39
+
40
+ # @api public
41
+ # @since 0.1.0
42
+ UnresolvedPluginDependencyError = Class.new(PluginError)
43
+
44
+ # @api public
45
+ # @since 0.1.0
46
+ AlreadyRegisteredPluginError = Class.new(PluginError)
47
+
48
+ # @api public
49
+ # @since 0.1.0
50
+ UnregisteredPluginError = Class.new(PluginError)
51
+
52
+ # @api public
53
+ # @since 0.1.0
54
+ TypeSystemError = Class.new(Error)
55
+
56
+ # @api public
57
+ # @since 0.1.0
58
+ TypeAliasNotFoundError = Class.new(TypeSystemError)
59
+
60
+ # @api public
61
+ # @since 0.1.0
62
+ IncorrectTypeSystemInteropError = Class.new(TypeSystemError)
63
+
64
+ # @api public
65
+ # @since 0.1.0
66
+ IncorrectTypeObjectError = Class.new(TypeSystemError)
67
+
68
+ # @api public
69
+ # @since 0.1.0
70
+ UnsupportedTypeSystemError = Class.new(TypeSystemError)
71
+
72
+ # @api public
73
+ # @since 0.1.0
74
+ UnsupportedTypeOperationError = Class.new(TypeSystemError)
75
+
76
+ # @api public
77
+ # @since 0.1.0
78
+ TypeCastingUnsupportedError = Class.new(UnsupportedTypeOperationError)
35
79
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::Plugins
6
+ require_relative 'plugins/abstract'
7
+ require_relative 'plugins/registry'
8
+ require_relative 'plugins/registry_interface.rb'
9
+ require_relative 'plugins/access_mixin'
10
+ require_relative 'plugins/thy_types'
11
+
12
+ # @since 0.1.0
13
+ extend SmartCore::Initializer::Plugins::RegistryInterface
14
+
15
+ # @since 0.1.0
16
+ register_plugin('thy_types', SmartCore::Initializer::Plugins::ThyTypes)
17
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Plugins::Abstract
6
+ class << self
7
+ # @param child_klass [Class]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 0.1.0
12
+ def inherited(child_klass)
13
+ child_klass.instance_variable_set(:@__loaded__, false)
14
+ child_klass.instance_variable_set(:@__lock__, Mutex.new)
15
+ super
16
+ end
17
+
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def load!
23
+ __thread_safe__ do
24
+ unless @__loaded__
25
+ @__loaded__ = true
26
+ install!
27
+ end
28
+ end
29
+ end
30
+
31
+ # @return [Boolean]
32
+ #
33
+ # @api private
34
+ # @since 0.1.0
35
+ def loaded?
36
+ __thread_safe__ { @__loaded__ }
37
+ end
38
+
39
+ private
40
+
41
+ # @return [void]
42
+ #
43
+ # @api private
44
+ # @since 0.1.0
45
+ def install!; end
46
+
47
+ # @return [Any]
48
+ #
49
+ # @api private
50
+ # @since 0.1.0
51
+ def __thread_safe__
52
+ @__lock__.synchronize { yield }
53
+ end
54
+ end
55
+ end