smart_initializer 0.1.0.alpha4 → 0.1.0

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 (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
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::TypeSystem::Interop::Aliasing::AliasList
6
+ # @param interop_klass [Class<SmartCore::Initializer::TypeSystem::Interop>]
7
+ # @return [void]
8
+ #
9
+ # @api private
10
+ # @since 0.1.0
11
+ def initialize(interop_klass)
12
+ @interop_klass = interop_klass
13
+ @list = {}
14
+ @lock = SmartCore::Engine::Lock.new
15
+ end
16
+
17
+ # @return [Array<String>]
18
+ #
19
+ # @api private
20
+ # @since 0.1.0
21
+ def keys
22
+ thread_safe { registered_aliases }
23
+ end
24
+
25
+ # @return [Hash<String,Any>]
26
+ #
27
+ # @api private
28
+ # @since 0.1.0
29
+ def to_h
30
+ thread_safe { transform_to_hash }
31
+ end
32
+ alias_method :to_hash, :to_h
33
+
34
+ # @param alias_name [String, Symbol]
35
+ # @param type [Any]
36
+ # @return [void]
37
+ #
38
+ # @api private
39
+ # @since 0.1.0
40
+ def associate(alias_name, type)
41
+ interop_klass.prevent_incompatible_type!(type)
42
+ thread_safe { set_alias(alias_name, type) }
43
+ end
44
+
45
+ # @param alias_name [String, Symbol]
46
+ # @return [Any]
47
+ #
48
+ # @api private
49
+ # @since 0.1.0
50
+ def resolve(alias_name)
51
+ thread_safe { get_alias(alias_name) }
52
+ end
53
+
54
+ private
55
+
56
+ # @return [Hash<String,Any>]
57
+ #
58
+ # @api private
59
+ # @since 0.1.0
60
+ attr_reader :list
61
+
62
+ # @return [Class<SmartCore::Initializer::TypeSystem::Interop>]
63
+ #
64
+ # @api private
65
+ # @since 0.1.0
66
+ attr_reader :interop_klass
67
+
68
+ # @param block [Block]
69
+ # @return [Any]
70
+ #
71
+ # @api private
72
+ # @since 0.1.0
73
+ def thread_safe(&block)
74
+ @lock.synchronize(&block)
75
+ end
76
+
77
+ # @param alias_name [String, Symbol]
78
+ # @param type [Any]
79
+ # @return [void]
80
+ #
81
+ # @api private
82
+ # @since 0.1.0
83
+ def set_alias(alias_name, type)
84
+ alias_name = normalized_alias(alias_name)
85
+
86
+ if list.key?(alias_name)
87
+ ::Warning.warn(
88
+ "[#{interop_klass.name}] Shadowing of the already existing \"#{alias_name}\" type alias."
89
+ )
90
+ end
91
+
92
+ list[alias_name] = type
93
+ end
94
+
95
+ # @param alias_name [String, Symbol]
96
+ # @return [Any]
97
+ #
98
+ # @api private
99
+ # @since 0.1.0
100
+ def get_alias(alias_name)
101
+ alias_name = normalized_alias(alias_name)
102
+
103
+ begin
104
+ list.fetch(alias_name)
105
+ rescue ::KeyError
106
+ raise(SmartCore::Initializer::TypeAliasNotFoundError, <<~ERROR_MESSAGE)
107
+ Alias with name "#{alias_name}" not found.
108
+ ERROR_MESSAGE
109
+ end
110
+ end
111
+
112
+ # @param alias_name [String, Symbol]
113
+ # @return [String]
114
+ #
115
+ # @api private
116
+ # @since 0.1.0
117
+ def normalized_alias(alias_name)
118
+ raise(
119
+ SmartCore::Initializer::ArgumentError,
120
+ 'Type alias should be a type of string or symbol'
121
+ ) unless alias_name.is_a?(String) || alias_name.is_a?(Symbol)
122
+
123
+ alias_name.to_s
124
+ end
125
+
126
+ # @return [Hash<String,Any>]
127
+ #
128
+ # @api private
129
+ # @since 0.1.0
130
+ def transform_to_hash
131
+ list.to_h
132
+ end
133
+
134
+ # @return [Array<String>]
135
+ #
136
+ # @api private
137
+ # @since 0.1.0
138
+ def registered_aliases
139
+ list.keys
140
+ end
141
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @abstract
4
+ # @api private
5
+ # @since 0.1.0
6
+ class SmartCore::Initializer::TypeSystem::Interop::Operation
7
+ # @param type [Any]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 0.1.0
12
+ def initialize(type)
13
+ @type = type
14
+ end
15
+
16
+ # @param value [Any]
17
+ # @return [Any]
18
+ #
19
+ # @api private
20
+ # @since 0.1.0
21
+ def call(value); end
22
+
23
+ private
24
+
25
+ # @return [Any]
26
+ #
27
+ # @api private
28
+ # @since 0.1.0
29
+ attr_reader :type
30
+ end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::TypeSystem::Registry
6
+ # @since 0.1.0
7
+ include Enumerable
8
+
9
+ # @return [void]
10
+ #
11
+ # @api private
12
+ # @since 0.1.0
13
+ def initialize
14
+ @systems = {}
15
+ @lock = SmartCore::Engine::Lock.new
16
+ end
17
+
18
+ # @param system_identifier [String, Symbol]
19
+ # @param interop_klass [Class<SmartCore::Initializer::TypeSystem::Interop>]
20
+ # @return [void]
21
+ #
22
+ # @api private
23
+ # @since 0.1.0
24
+ def register(system_identifier, interop_klass)
25
+ thread_safe { apply(system_identifier, interop_klass) }
26
+ end
27
+
28
+ # @param system_identifier [String, Symbol]
29
+ # @return [Class<SmartCore::Initializer::TypeSystem::Interop>]
30
+ #
31
+ # @api private
32
+ # @since 0.1.0
33
+ def resolve(system_identifier)
34
+ thread_safe { fetch(system_identifier) }
35
+ end
36
+
37
+ # @return [Array<String>]
38
+ #
39
+ # @api private
40
+ # @since 0.1.0
41
+ def names
42
+ thread_safe { system_names }
43
+ end
44
+
45
+ # @return [Array<Class<SmartCore::Initializer::TypeSystem::Interop>>]
46
+ #
47
+ # @api private
48
+ # @since 0.1.0
49
+ def interops
50
+ thread_safe { system_interops }
51
+ end
52
+
53
+ # @param block [Block]
54
+ # @yield [system_name, system_interop]
55
+ # @yieldparam system_name [String]
56
+ # @yieldparam system_interop [Class<SmartCore::Initializer::TypeSystem::Interop>]
57
+ # @return [Enumerable]
58
+ #
59
+ # @api private
60
+ # @since 0.1.0
61
+ def each(&block)
62
+ thread_safe { iterate(&block) }
63
+ end
64
+
65
+ # @return [Hash<String,Class<SmartCore::Initializer::TypeSystem::Interop>]
66
+ #
67
+ # @api private
68
+ # @since 0.1.0
69
+ def to_h
70
+ thread_safe { systems.dup }
71
+ end
72
+ alias_method :to_hash, :to_h
73
+
74
+ private
75
+
76
+ # @return [Hash<String,Class<SmartCore::Initializer::TypeSystem::Interop>]
77
+ #
78
+ # @api private
79
+ # @since 0.1.0
80
+ attr_reader :systems
81
+
82
+ # @return [Array<String>]
83
+ #
84
+ # @pai private
85
+ # @since 0.1.0
86
+ def system_names
87
+ systems.keys
88
+ end
89
+
90
+ # @return [Array<Class<SmartCore::Initializer::TypeSystem::Interop>>]
91
+ #
92
+ # @api private
93
+ # @since 0.1.0
94
+ def system_interops
95
+ systems.values
96
+ end
97
+
98
+ # @param block [Block]
99
+ # @yield [system_name, system_interop]
100
+ # @yieldparam system_name [String]
101
+ # @yieldparam system_interop [Class<SmartCore::Initializer::TypeSystem::Interop>]
102
+ # @return [Enumerable]
103
+ #
104
+ # @api private
105
+ # @since 0.1.0
106
+ def iterate(&block)
107
+ block_given? ? systems.each_pair(&block) : systems.each_pair
108
+ end
109
+
110
+ # @param system_identifier [String, Symbol]
111
+ # @param interop_klass [Class<SmartCore::Initializer::TypeSystem::Interop>]
112
+ # @return [void]
113
+ #
114
+ # @api private
115
+ # @since 0.1.0
116
+ def apply(system_identifier, interop_klass)
117
+ prevent_incorrect_system_interop!(interop_klass)
118
+ identifier = indifferently_accessible_identifier(system_identifier)
119
+ systems[identifier] = interop_klass
120
+ end
121
+
122
+ # @param system_identifier [String, Symbol]
123
+ # @return [Class<SmartCore::Initializer::TypeSystem::Interop>]
124
+ #
125
+ # @raise [SmartCore::Initializer::UnsupportedTypeSystemError]
126
+ #
127
+ # @api private
128
+ # @since 0.1.0
129
+ def fetch(system_identifier)
130
+ identifier = indifferently_accessible_identifier(system_identifier)
131
+
132
+ begin
133
+ systems.fetch(identifier)
134
+ rescue ::KeyError
135
+ raise(SmartCore::Initializer::UnsupportedTypeSystemError, <<~ERROR_MESSAGE)
136
+ "#{identifier}" type system is not supported.
137
+ ERROR_MESSAGE
138
+ end
139
+ end
140
+
141
+ # @param interop_klass [Class<SMartCore::Initializer::TypeSystem::Interop>]
142
+ # @return [void]
143
+ #
144
+ # @raise [SmartCore::Initializer::IncorrectTypeSystemInteropError]
145
+ #
146
+ # @api private
147
+ # @since 0.1.0
148
+ def prevent_incorrect_system_interop!(interop_klass)
149
+ unless interop_klass.is_a?(Class) && interop_klass < SmartCore::Initializer::TypeSystem::Interop
150
+ raise(
151
+ SmartCore::Initializer::IncorrectTypeSystemInteropError,
152
+ 'Incorrect type system interop class.'
153
+ )
154
+ end
155
+ end
156
+
157
+ # @param system_identifier [String, Symbol]
158
+ # @return [String]
159
+ #
160
+ # @api private
161
+ # @since 0.1.0
162
+ def indifferently_accessible_identifier(system_identifier)
163
+ system_identifier.to_s.clone.tap(&:freeze)
164
+ end
165
+
166
+ # @param block [Block]
167
+ # @return [Any]
168
+ #
169
+ # @api private
170
+ # @since 0.1.0
171
+ def thread_safe(&block)
172
+ @lock.synchronize(&block)
173
+ end
174
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::TypeSystem::RegistryInterface
6
+ class << self
7
+ # @param base_module [Class, Module]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 0.1.0
12
+ def extended(base_module)
13
+ base_module.instance_variable_set(
14
+ :@registry, SmartCore::Initializer::TypeSystem::Registry.new
15
+ )
16
+ base_module.instance_variable_set(
17
+ :@access_lock, SmartCore::Engine::Lock.new
18
+ )
19
+ end
20
+ end
21
+
22
+ # @option system_identifier [String, Symbol]
23
+ # @option type [Any]
24
+ # @return [SmartCore::Initializer::TypeSystem::Interop]
25
+ #
26
+ # @api private
27
+ # @since 0.1.0
28
+ def build_interop(system: system_identifier, type: type_object)
29
+ thread_safe { registry.resolve(system_identifier).create(type_object) }
30
+ end
31
+
32
+ # @param identifier [String, Symbol]
33
+ # @param interop_klass [Class<SmartCore::Initializer::TypeSystem::Interop>]
34
+ # @return [void]
35
+ #
36
+ # @api private
37
+ # @since 0.1.0
38
+ def register(identifier, interop_klass)
39
+ thread_safe { registry.register(identifier, interop_klass) }
40
+ end
41
+
42
+ # @param identifier [String, Symbol]
43
+ # @return [Class<SmartCore::Initializer::TypeSystem::Interop>]
44
+ #
45
+ # @api private
46
+ # @since 0.1.0
47
+ def resolve(identifier)
48
+ thread_safe { registry.resolve(identifier) }
49
+ end
50
+ alias_method :[], :resolve
51
+
52
+ # @return [Array<String>]
53
+ #
54
+ # @api public
55
+ # @since 0.1.0
56
+ def names
57
+ thread_safe { registry.names }
58
+ end
59
+
60
+ # @return [Array<Class<SmartCore::Initializer::TypeSystem::Interop>>]
61
+ #
62
+ # @api public
63
+ # @since 0.1.0
64
+ def systems
65
+ thread_safe { registry.to_h }
66
+ end
67
+
68
+ # @param block [Block]
69
+ # @yield [system_name, system_interop]
70
+ # @yieldparam system_name [String]
71
+ # @yieldparam system_interop [Class<SmartCore::Initializer::TypeSystem::Interop>]
72
+ # @return [Enumerable]
73
+ #
74
+ # @api public
75
+ # @since 0.1.0
76
+ def each(&block)
77
+ thread_safe { registry.each(&block) }
78
+ end
79
+
80
+ private
81
+
82
+ # @return [SmartCore::Initializer::TypeSystem::Registry]
83
+ #
84
+ # @api private
85
+ # @since 0.1.0
86
+ attr_reader :registry
87
+
88
+ # @return [SmartCore::Engine::Lock]
89
+ #
90
+ # @api private
91
+ # @since 0.1.0
92
+ attr_reader :access_lock
93
+
94
+ # @param block [Block]
95
+ # @return [Any]
96
+ #
97
+ # @api pribate
98
+ # @since 0.1.0
99
+ def thread_safe(&block)
100
+ access_lock.synchronize(&block)
101
+ end
102
+ end