smart_initializer 0.1.0.alpha2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +36 -5
  4. data/CHANGELOG.md +15 -0
  5. data/Gemfile.lock +63 -43
  6. data/README.md +263 -11
  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 +102 -0
  11. data/gemfiles/without_external_deps.gemfile +5 -0
  12. data/gemfiles/without_external_deps.gemfile.lock +100 -0
  13. data/lib/smart_core/initializer.rb +44 -28
  14. data/lib/smart_core/initializer/attribute.rb +12 -5
  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/configuration.rb +33 -0
  18. data/lib/smart_core/initializer/constructor.rb +60 -23
  19. data/lib/smart_core/initializer/{attribute → constructor}/definer.rb +64 -12
  20. data/lib/smart_core/initializer/dsl.rb +47 -10
  21. data/lib/smart_core/initializer/dsl/inheritance.rb +1 -0
  22. data/lib/smart_core/initializer/errors.rb +44 -0
  23. data/lib/smart_core/initializer/extensions.rb +9 -0
  24. data/lib/smart_core/initializer/extensions/abstract.rb +8 -0
  25. data/lib/smart_core/initializer/extensions/ext_init.rb +31 -0
  26. data/lib/smart_core/initializer/extensions/list.rb +74 -0
  27. data/lib/smart_core/initializer/functionality.rb +36 -0
  28. data/lib/smart_core/initializer/instance_attribute_accessing.rb +51 -0
  29. data/lib/smart_core/initializer/plugins.rb +17 -0
  30. data/lib/smart_core/initializer/plugins/abstract.rb +55 -0
  31. data/lib/smart_core/initializer/plugins/access_mixin.rb +47 -0
  32. data/lib/smart_core/initializer/plugins/registry.rb +166 -0
  33. data/lib/smart_core/initializer/plugins/registry_interface.rb +77 -0
  34. data/lib/smart_core/initializer/plugins/thy_types.rb +30 -0
  35. data/lib/smart_core/initializer/plugins/thy_types/errors.rb +11 -0
  36. data/lib/smart_core/initializer/plugins/thy_types/thy_types.rb +23 -0
  37. data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +78 -0
  38. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation.rb +12 -0
  39. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/base.rb +9 -0
  40. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/cast.rb +21 -0
  41. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/valid.rb +16 -0
  42. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/validate.rb +19 -0
  43. data/lib/smart_core/initializer/settings.rb +49 -0
  44. data/lib/smart_core/initializer/settings/duplicator.rb +20 -0
  45. data/lib/smart_core/initializer/settings/type_system.rb +69 -0
  46. data/lib/smart_core/initializer/type_system.rb +16 -0
  47. data/lib/smart_core/initializer/type_system/interop.rb +103 -0
  48. data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +70 -0
  49. data/lib/smart_core/initializer/type_system/interop/aliasing.rb +72 -0
  50. data/lib/smart_core/initializer/type_system/interop/aliasing/alias_list.rb +141 -0
  51. data/lib/smart_core/initializer/type_system/interop/operation.rb +30 -0
  52. data/lib/smart_core/initializer/type_system/registry.rb +174 -0
  53. data/lib/smart_core/initializer/type_system/registry_interface.rb +102 -0
  54. data/lib/smart_core/initializer/type_system/smart_types.rb +48 -0
  55. data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +72 -0
  56. data/lib/smart_core/initializer/type_system/smart_types/operation.rb +13 -0
  57. data/lib/smart_core/initializer/type_system/smart_types/operation/base.rb +8 -0
  58. data/lib/smart_core/initializer/type_system/smart_types/operation/cast.rb +16 -0
  59. data/lib/smart_core/initializer/type_system/smart_types/operation/valid.rb +16 -0
  60. data/lib/smart_core/initializer/type_system/smart_types/operation/validate.rb +16 -0
  61. data/lib/smart_core/initializer/version.rb +2 -1
  62. data/smart_initializer.gemspec +13 -9
  63. metadata +73 -17
  64. data/lib/smart_core/initializer/type_aliasing.rb +0 -50
  65. data/lib/smart_core/initializer/type_aliasing/alias_list.rb +0 -101
@@ -13,6 +13,7 @@ module SmartCore::Initializer::DSL::Inheritance
13
13
  def inherit(base:, child:)
14
14
  child.__params__.concat(base.__params__)
15
15
  child.__options__.concat(base.__options__)
16
+ child.__init_extensions__.concat(base.__init_extensions__)
16
17
  end
17
18
  end
18
19
  end
@@ -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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::Extensions
6
+ require_relative 'extensions/abstract'
7
+ require_relative 'extensions/ext_init'
8
+ require_relative 'extensions/list'
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Extensions::Abstract
6
+ # @!method dup
7
+ # @return [SmartCore::Initializer::Extensions::Abstract]
8
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Extensions::ExtInit < SmartCore::Initializer::Extensions::Abstract
6
+ # @param extender [Proc]
7
+ # @return [void]
8
+ #
9
+ # @api private
10
+ # @since 0.1.0
11
+ def initialize(extender)
12
+ @extender = extender
13
+ end
14
+
15
+ # @param instance [Any]
16
+ # @return [void]
17
+ #
18
+ # @api private
19
+ # @since 0.1.0
20
+ def call(instance)
21
+ extender.call(instance)
22
+ end
23
+
24
+ private
25
+
26
+ # @return [Proc]
27
+ #
28
+ # @api private
29
+ # @since0 0.1.0
30
+ attr_reader :extender
31
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Extensions::List
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
+ @extensions = []
15
+ @lock = SmartCore::Engine::Lock.new
16
+ end
17
+
18
+ # @param extension [SmartCore::Initializer::Extensions::Abstract]
19
+ # @return [void]
20
+ #
21
+ # @api private
22
+ # @since 0.1.0
23
+ def add(extension)
24
+ thread_safe { extensions << extension }
25
+ end
26
+ alias_method :<<, :add
27
+
28
+ # @param list [SmartCore::Initializer::Extensions::List]
29
+ # @return [void]
30
+ #
31
+ # @api private
32
+ # @since 0.1.0
33
+ def concat(list)
34
+ thread_safe do
35
+ list.each { |extension| add(extension.dup) }
36
+ end
37
+ end
38
+
39
+ # @param block [Block]
40
+ # @return [Enumerable]
41
+ #
42
+ # @api private
43
+ # @since 0.1.0
44
+ def each(&block)
45
+ thread_safe do
46
+ block_given? ? extensions.each(&block) : extensions.each
47
+ end
48
+ end
49
+
50
+ # @return [Integer]
51
+ #
52
+ # @api private
53
+ # @since 0.1.0
54
+ def size
55
+ thread_safe { extensions.size }
56
+ end
57
+
58
+ private
59
+
60
+ # @return [Array<SmartCore::Initializer::Extensions::Abstract>]
61
+ #
62
+ # @api private
63
+ # @since 0.1.0
64
+ attr_reader :extensions
65
+
66
+ # @param block [Block]
67
+ # @return [Any]
68
+ #
69
+ # @api private
70
+ # @since 0.1.0
71
+ def thread_safe(&block)
72
+ @lock.synchronize(&block)
73
+ end
74
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.3.0
5
+ module SmartCore::Initializer::Functionality
6
+ # @return [NilClass]
7
+ #
8
+ # @api private
9
+ # @since 0.3.0
10
+ INITIAL_TYPE_SYSTEM = nil
11
+
12
+ class << self
13
+ # @option type_system [String, Symbol, NilClass]
14
+ # @return [Module]
15
+ #
16
+ # @api private
17
+ # @since 0.3.0
18
+ def includable_module(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
+
27
+ # @param base_klass [Class]
28
+ # @return [void]
29
+ #
30
+ # @api private
31
+ # @since 0.3.0
32
+ def seed_to(base_klass)
33
+ base_klass.extend(SmartCore::Initializer::DSL)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.3.0
5
+ module SmartCore::Initializer::InstanceAttributeAccessing
6
+ # @return [Hash<Symbol,Any>]
7
+ #
8
+ # @api public
9
+ # @since 0.3.0
10
+ def __params__
11
+ __collect_params__
12
+ end
13
+
14
+ # @return [Hash<Symbol,Any>]
15
+ #
16
+ # @api public
17
+ # @since 0.3.0
18
+ def __options__
19
+ __collect_options__
20
+ end
21
+
22
+ # @return [Hash<Symbol,Any>]
23
+ #
24
+ # @api public
25
+ # @since 0.3.0
26
+ def __attributes__
27
+ __collect_params__.merge(__collect_options__)
28
+ end
29
+
30
+ private
31
+
32
+ # @return [Hash<Symbol,Any>]
33
+ #
34
+ # @api private
35
+ # @since 0.3.0
36
+ def __collect_params__
37
+ self.class.__params__.each_with_object({}) do |param, memo|
38
+ memo[param.name] = instance_variable_get("@#{param.name}")
39
+ end
40
+ end
41
+
42
+ # @return [Hash<Symbol,Any>]
43
+ #
44
+ # @api private
45
+ # @since 0.3.0
46
+ def __collect_options__
47
+ self.class.__options__.each_with_object({}) do |option, memo|
48
+ memo[option.name] = instance_variable_get("@#{option.name}")
49
+ end
50
+ end
51
+ 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
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::Plugins::AccessMixin
6
+ # @param plugin_name [Symbol, String]
7
+ # @return [void]
8
+ #
9
+ # @see SmartCore::Initializer::Plugins
10
+ #
11
+ # @api public
12
+ # @since 0.1.0
13
+ def plugin(plugin_name)
14
+ SmartCore::Initializer::Plugins.load(plugin_name)
15
+ end
16
+
17
+ # @return [Array<String>]
18
+ #
19
+ # @see SmartCore::Initializer::Plugins
20
+ #
21
+ # @api public
22
+ # @since 0.1.0
23
+ def plugins
24
+ SmartCore::Initializer::Plugins.names
25
+ end
26
+
27
+ # @return [Hash<String,Class<SmartCore::Initializer::Plugins::Abstract>>]
28
+ #
29
+ # @api private
30
+ # @since 0.1.0
31
+ def loaded_plugins
32
+ SmartCore::Initializer::Plugins.loaded_plugins
33
+ end
34
+ alias_method :enabled_plugins, :loaded_plugins
35
+
36
+ # @param plugin_name [String, Symbol]
37
+ # @param plugin_klass [Class<SmartCore::Initializer::Plugins::Abstract>]
38
+ # @return [void]
39
+ #
40
+ # @see SmartCore::Initializer::Plugins
41
+ #
42
+ # @api public
43
+ # @since 0.1.0
44
+ def register_plugin(plugin_name, plugin_klass)
45
+ SmartCore::Initializer::Plugins.register_plugin(plugin_name, plugin_klass)
46
+ end
47
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Plugins::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
+ @plugin_set = {}
15
+ @access_lock = Mutex.new
16
+ end
17
+
18
+ # @param plugin_name [Symbol, String]
19
+ # @return [SmartCore::Initializer::Plugins::Abstract]
20
+ #
21
+ # @api private
22
+ # @since 0.1.0
23
+ def [](plugin_name)
24
+ thread_safe { fetch(plugin_name) }
25
+ end
26
+
27
+ # @param plugin_name [Symbol, String]
28
+ # @param plugin_module [SmartCore::Initializer::Plugins::Abstract]
29
+ # @return [void]
30
+ #
31
+ # @api private
32
+ # @since 0.1.0
33
+ def register(plugin_name, plugin_module)
34
+ thread_safe { apply(plugin_name, plugin_module) }
35
+ end
36
+ alias_method :[]=, :register
37
+
38
+ # @return [Array<String>]
39
+ #
40
+ # @api private
41
+ # @since 0.1.0
42
+ def names
43
+ thread_safe { plugin_names }
44
+ end
45
+
46
+ # @return [Hash<String,Class<SmartCore::Initializer::Plugins::Abstract>>]
47
+ #
48
+ # @api private
49
+ # @since 0.1.0
50
+ def loaded
51
+ thread_safe { loaded_plugins }
52
+ end
53
+
54
+ # @param block [Block]
55
+ # @return [Enumerable]
56
+ #
57
+ # @api private
58
+ # @since 0.1.0
59
+ def each(&block)
60
+ thread_safe { iterate(&block) }
61
+ end
62
+
63
+ private
64
+
65
+ # @return [Hash]
66
+ #
67
+ # @api private
68
+ # @since 0.1.0
69
+ attr_reader :plugin_set
70
+
71
+ # @return [Mutex]
72
+ #
73
+ # @api private
74
+ # @since 0.1.0
75
+ attr_reader :access_lock
76
+
77
+ # @return [void]
78
+ #
79
+ # @api private
80
+ # @since 0.1.0
81
+ def thread_safe
82
+ access_lock.synchronize { yield if block_given? }
83
+ end
84
+
85
+ # @return [Array<String>]
86
+ #
87
+ # @api private
88
+ # @since 0.1.0
89
+ def plugin_names
90
+ plugin_set.keys
91
+ end
92
+
93
+ # @param block [Block]
94
+ # @return [Enumerable]
95
+ #
96
+ # @api private
97
+ # @since 0.1.0
98
+ def iterate(&block)
99
+ block_given? ? plugin_set.each_pair(&block) : plugin_set.each_pair
100
+ end
101
+
102
+ # @param plugin_name [String]
103
+ # @return [Boolean]
104
+ #
105
+ # @api private
106
+ # @since 0.1.0
107
+ def registered?(plugin_name)
108
+ plugin_set.key?(plugin_name)
109
+ end
110
+
111
+ # @return [Array<SmartCore::Initializer::Plugins::Abstract>]
112
+ #
113
+ # @api private
114
+ # @since 0.1.0
115
+ def loaded_plugins
116
+ plugin_set.select { |_plugin_name, plugin_module| plugin_module.loaded? }
117
+ end
118
+
119
+ # @param plugin_name [Symbol, String]
120
+ # @param plugin_module [SmartCore::Initializer::Plugins::Abstract]
121
+ # @return [void]
122
+ #
123
+ # @raise [SmartCore::Initializer::AlreadyRegisteredPluginError]
124
+ #
125
+ # @api private
126
+ # @since 0.1.0
127
+ def apply(plugin_name, plugin_module)
128
+ plugin_name = indifferently_accessible_plugin_name(plugin_name)
129
+
130
+ if registered?(plugin_name)
131
+ raise(SmartCore::Initializer::AlreadyRegisteredPluginError, <<~ERROR_MESSAGE)
132
+ #{plugin_name} plugin already exists
133
+ ERROR_MESSAGE
134
+ end
135
+
136
+ plugin_set[plugin_name] = plugin_module
137
+ end
138
+
139
+ # @param plugin_name [Symbol, String]
140
+ # @return [SmartCore::Initializer::Plugins::Abstract]
141
+ #
142
+ # @raise [SmartCore::Initializer::UnregisteredPluginError]
143
+ #
144
+ # @api private
145
+ # @since 0.1.0
146
+ def fetch(plugin_name)
147
+ plugin_name = indifferently_accessible_plugin_name(plugin_name)
148
+
149
+ unless registered?(plugin_name)
150
+ raise(SmartCore::Initializer::UnregisteredPluginError, <<~ERROR_MESSAGE)
151
+ #{plugin_name} plugin is not registered
152
+ ERROR_MESSAGE
153
+ end
154
+
155
+ plugin_set[plugin_name]
156
+ end
157
+
158
+ # @param key [Symbol, String]
159
+ # @return [String]
160
+ #
161
+ # @api private
162
+ # @since 0.1.0
163
+ def indifferently_accessible_plugin_name(plugin_name)
164
+ plugin_name.to_s
165
+ end
166
+ end