rggen-core 0.21.0 → 0.25.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +2 -1
  4. data/exe/rggen +2 -2
  5. data/lib/rggen/core.rb +9 -2
  6. data/lib/rggen/core/base/component.rb +5 -6
  7. data/lib/rggen/core/base/component_factory.rb +8 -5
  8. data/lib/rggen/core/builder/builder.rb +29 -35
  9. data/lib/rggen/core/builder/component_registry.rb +8 -9
  10. data/lib/rggen/core/builder/feature_registry.rb +15 -15
  11. data/lib/rggen/core/builder/layer.rb +44 -29
  12. data/lib/rggen/core/builder/list_feature_entry.rb +5 -9
  13. data/lib/rggen/core/builder/loader_registry.rb +1 -2
  14. data/lib/rggen/core/builder/plugin_manager.rb +122 -0
  15. data/lib/rggen/core/builder/plugin_spec.rb +83 -0
  16. data/lib/rggen/core/builder/simple_feature_entry.rb +4 -4
  17. data/lib/rggen/core/configuration.rb +3 -2
  18. data/lib/rggen/core/configuration/toml_loader.rb +18 -0
  19. data/lib/rggen/core/core_extensions/object.rb +4 -4
  20. data/lib/rggen/core/dsl.rb +3 -1
  21. data/lib/rggen/core/exceptions.rb +9 -4
  22. data/lib/rggen/core/facets.rb +1 -1
  23. data/lib/rggen/core/generator.rb +3 -3
  24. data/lib/rggen/core/input_base/component.rb +12 -0
  25. data/lib/rggen/core/input_base/component_factory.rb +1 -0
  26. data/lib/rggen/core/input_base/feature.rb +22 -8
  27. data/lib/rggen/core/input_base/input_data.rb +24 -17
  28. data/lib/rggen/core/input_base/input_matcher.rb +5 -5
  29. data/lib/rggen/core/input_base/loader.rb +15 -15
  30. data/lib/rggen/core/input_base/property.rb +17 -11
  31. data/lib/rggen/core/input_base/toml_loader.rb +16 -0
  32. data/lib/rggen/core/input_base/yaml_loader.rb +1 -18
  33. data/lib/rggen/core/options.rb +18 -14
  34. data/lib/rggen/core/output_base/code_generator.rb +5 -6
  35. data/lib/rggen/core/output_base/document_component_factory.rb +10 -0
  36. data/lib/rggen/core/output_base/feature.rb +15 -11
  37. data/lib/rggen/core/output_base/file_writer.rb +1 -1
  38. data/lib/rggen/core/output_base/source_file_component_factory.rb +15 -0
  39. data/lib/rggen/core/output_base/template_engine.rb +4 -5
  40. data/lib/rggen/core/plugin.rb +16 -0
  41. data/lib/rggen/core/printers.rb +11 -7
  42. data/lib/rggen/core/register_map.rb +4 -5
  43. data/lib/rggen/core/register_map/hash_loader.rb +6 -9
  44. data/lib/rggen/core/register_map/toml_loader.rb +18 -0
  45. data/lib/rggen/core/utility/attribute_setter.rb +5 -0
  46. data/lib/rggen/core/utility/code_utility/code_block.rb +11 -5
  47. data/lib/rggen/core/utility/error_utility.rb +33 -6
  48. data/lib/rggen/core/version.rb +2 -4
  49. metadata +33 -7
  50. data/lib/rggen/core/base/proxy_call.rb +0 -18
  51. data/lib/rggen/core/builder/plugins.rb +0 -79
@@ -15,11 +15,11 @@ module RgGen
15
15
  attr_reader :registry
16
16
  attr_reader :name
17
17
 
18
- def setup(base_feature, base_factory, context, body)
18
+ def setup(base_feature, base_factory, context, &body)
19
19
  @base_feature = Class.new(base_feature)
20
20
  @factory = Class.new(base_factory)
21
21
  context && attach_shared_context(context)
22
- body && Docile.dsl_eval(self, @name, &body)
22
+ block_given? && Docile.dsl_eval(self, @name, &body)
23
23
  end
24
24
 
25
25
  def match_entry_type?(entry_type)
@@ -49,9 +49,8 @@ module RgGen
49
49
  @features[feature_name] ||= Class.new(@base_feature)
50
50
  feature = @features[feature_name]
51
51
  if context
52
- feature.method_defined?(:shared_context) && (
53
- raise BuilderError.new('shared context has already been set')
54
- )
52
+ feature.method_defined?(:shared_context) &&
53
+ (raise BuilderError.new('shared context has already been set'))
55
54
  feature.attach_context(context)
56
55
  end
57
56
  body && feature.class_exec(feature_name, &body)
@@ -87,10 +86,7 @@ module RgGen
87
86
  end
88
87
 
89
88
  def target_features(enabled_features)
90
- enabled_features
91
- .select { |n| @features.key?(n) }
92
- .map { |n| [n, @features[n]] }
93
- .to_h
89
+ @features.slice(*enabled_features)
94
90
  end
95
91
  end
96
92
  end
@@ -19,8 +19,7 @@ module RgGen
19
19
  end
20
20
 
21
21
  def define_value_extractor(layers, value, &body)
22
- @extractors <<
23
- create_extractor(layers, value, &body)
22
+ @extractors << create_extractor(layers, value, &body)
24
23
  end
25
24
 
26
25
  def ignore_value(layers, value)
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class PluginRegistry
7
+ def initialize(plugin_module, &block)
8
+ @plugin_module = plugin_module
9
+ @block = block
10
+ end
11
+
12
+ def default_setup(builder)
13
+ @plugin_module.plugin_spec.activate(builder)
14
+ end
15
+
16
+ def optional_setup(builder)
17
+ @block && @plugin_module.instance_exec(builder, &@block)
18
+ end
19
+
20
+ def version_info
21
+ @plugin_module.plugin_spec.version_info
22
+ end
23
+ end
24
+
25
+ class PluginManager
26
+ def initialize(builder)
27
+ @builder = builder
28
+ @plugins = []
29
+ end
30
+
31
+ def load_plugin(setup_path_or_name)
32
+ setup_path_or_name = setup_path_or_name.to_s.strip
33
+ setup_path =
34
+ if setup_file_directly_given?(setup_path_or_name)
35
+ setup_path_or_name
36
+ else
37
+ get_setup_path(setup_path_or_name)
38
+ end
39
+ read_setup_file(setup_path, setup_path_or_name)
40
+ end
41
+
42
+ def load_plugins(plugins, no_default_plugins, activation = true)
43
+ RgGen.builder(@builder)
44
+ merge_plugins(plugins, no_default_plugins).each(&method(:load_plugin))
45
+ activation && activate_plugins
46
+ end
47
+
48
+ def register_plugin(plugin_module, &block)
49
+ plugin?(plugin_module) ||
50
+ (raise Core::PluginError.new('no plugin spec is given'))
51
+ @plugins << PluginRegistry.new(plugin_module, &block)
52
+ end
53
+
54
+ def activate_plugins(**options)
55
+ options[:no_default_setup] ||
56
+ @plugins.each { |plugin| plugin.default_setup(@builder) }
57
+ options[:no_optional_setup] ||
58
+ @plugins.each { |plugin| plugin.optional_setup(@builder) }
59
+ end
60
+
61
+ def version_info
62
+ @plugins.map(&:version_info)
63
+ end
64
+
65
+ private
66
+
67
+ def setup_file_directly_given?(setup_path_or_name)
68
+ File.ext(setup_path_or_name) == 'rb' ||
69
+ File.basename(setup_path_or_name, '.*') == 'setup'
70
+ end
71
+
72
+ def get_setup_path(name)
73
+ base, sub_directory = name.split('/', 2)
74
+ base = base.sub(/^rggen[-_]/, '').tr('-', '_')
75
+ File.join(*['rggen', base, sub_directory, 'setup'].compact)
76
+ end
77
+
78
+ def read_setup_file(setup_path, setup_path_or_name)
79
+ require setup_path
80
+ rescue ::LoadError
81
+ message =
82
+ if setup_path_or_name == setup_path
83
+ "cannot load such plugin: #{setup_path_or_name}"
84
+ else
85
+ "cannot load such plugin: #{setup_path_or_name} (#{setup_path})"
86
+ end
87
+ raise Core::PluginError.new(message)
88
+ end
89
+
90
+ def merge_plugins(plugins, no_default_plugins)
91
+ [
92
+ *default_plugins(no_default_plugins),
93
+ *plugins_from_env,
94
+ *plugins
95
+ ]
96
+ end
97
+
98
+ DEFAULT_PLUGSINS = 'rggen/setup'
99
+
100
+ def default_plugins(no_default_plugins)
101
+ load_default_plugins?(no_default_plugins) && DEFAULT_PLUGSINS || nil
102
+ end
103
+
104
+ def load_default_plugins?(no_default_plugins)
105
+ return false if no_default_plugins
106
+ return false if ENV.key?('RGGEN_NO_DEFAULT_PLUGINS')
107
+ return false if Gem.find_files(DEFAULT_PLUGSINS).empty?
108
+ true
109
+ end
110
+
111
+ def plugins_from_env
112
+ ENV['RGGEN_PLUGINS']
113
+ &.split(':')&.map(&:strip)&.reject(&:empty?)
114
+ end
115
+
116
+ def plugin?(plugin_module)
117
+ plugin_module.respond_to?(:plugin_spec) && plugin_module.plugin_spec
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class PluginSpec
7
+ def initialize(name, plugin_module)
8
+ @name = name
9
+ @plugin_module = plugin_module
10
+ @component_registrations = []
11
+ @loader_registrations = []
12
+ @files = []
13
+ end
14
+
15
+ def version(value = nil)
16
+ @version = value if value
17
+ version_value
18
+ end
19
+
20
+ def version_info
21
+ "#{@name} #{version}"
22
+ end
23
+
24
+ def register_component(component, layers = nil, &body)
25
+ @component_registrations << [component, layers, body]
26
+ end
27
+
28
+ def register_loader(component, loader_type, loader)
29
+ @loader_registrations << [component, loader_type, loader]
30
+ end
31
+
32
+ def register_loaders(component, loader_type, loaders)
33
+ Array(loaders)
34
+ .each { |loader| register_loader(component, loader_type, loader) }
35
+ end
36
+
37
+ def register_files(files)
38
+ root = File.dirname(caller_locations(1, 1).first.path)
39
+ files.each { |file| @files << File.join(root, file) }
40
+ end
41
+
42
+ alias_method :files, :register_files
43
+
44
+ def activate(builder)
45
+ activate_components(builder)
46
+ activate_loaders(builder)
47
+ load_files
48
+ end
49
+
50
+ private
51
+
52
+ DEFAULT_VERSION = '0.0.0'
53
+
54
+ def version_value
55
+ @version || const_version || DEFAULT_VERSION
56
+ end
57
+
58
+ def const_version
59
+ @plugin_module.const_defined?(:VERSION) &&
60
+ @plugin_module.const_get(:VERSION)
61
+ end
62
+
63
+ def activate_components(builder)
64
+ @component_registrations.each do |component, layers, body|
65
+ builder
66
+ .output_component_registry(component)
67
+ .register_component(layers, &body)
68
+ end
69
+ end
70
+
71
+ def activate_loaders(builder)
72
+ @loader_registrations.each do |component, loader_type, loader|
73
+ builder.register_loader(component, loader_type, loader)
74
+ end
75
+ end
76
+
77
+ def load_files
78
+ @files.each(&method(:require))
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -12,8 +12,8 @@ module RgGen
12
12
  attr_reader :registry
13
13
  attr_reader :name
14
14
 
15
- def setup(base_feature, factory, context, body)
16
- @feature = define_feature(base_feature, context, body)
15
+ def setup(base_feature, factory, context, &body)
16
+ @feature = define_feature(base_feature, context, &body)
17
17
  @factory = factory
18
18
  end
19
19
 
@@ -27,10 +27,10 @@ module RgGen
27
27
 
28
28
  private
29
29
 
30
- def define_feature(base, context, body)
30
+ def define_feature(base, context, &body)
31
31
  feature = Class.new(base)
32
32
  context && feature.attach_context(context)
33
- body && feature.class_exec(@name, &body)
33
+ block_given? && feature.class_exec(@name, &body)
34
34
  feature
35
35
  end
36
36
  end
@@ -5,14 +5,15 @@ module RgGen
5
5
  module Configuration
6
6
  def self.setup(builder)
7
7
  builder.input_component_registry(:configuration) do
8
- register_component do
8
+ register_global_component do
9
9
  component Component, ComponentFactory
10
10
  feature Feature, FeatureFactory
11
11
  end
12
12
 
13
13
  register_loader :ruby, RubyLoader
14
- register_loader :yaml, YAMLLoader
15
14
  register_loader :json, JSONLoader
15
+ register_loader :toml, TOMLLoader
16
+ register_loader :yaml, YAMLLoader
16
17
  end
17
18
  end
18
19
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Configuration
6
+ class TOMLLoader < Loader
7
+ include HashLoader
8
+ include InputBase::TOMLLoader
9
+
10
+ support_types [:toml]
11
+
12
+ def read_file(file)
13
+ load_toml(file)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,10 +2,10 @@
2
2
 
3
3
  class Object
4
4
  def export_instance_variable(variable, to)
5
- return unless instance_variable_defined?(variable)
6
- v = instance_variable_get(variable)
7
- v = yield(v) if block_given?
8
- to.instance_variable_set(variable, v)
5
+ instance_variable_defined?(variable) &&
6
+ instance_variable_get(variable)
7
+ .yield_self { |v| block_given? ? yield(v) : v }
8
+ .yield_self { |v| to.instance_variable_set(variable, v) }
9
9
  end
10
10
 
11
11
  def singleton_exec(*args, &block)
@@ -15,11 +15,13 @@ module RgGen
15
15
  :define_simple_feature,
16
16
  :define_list_feature,
17
17
  :define_list_item_feature,
18
+ :define_value_extractor,
18
19
  :enable,
19
20
  :disable_all,
20
21
  :disable,
21
22
  :delete,
22
- :setup
23
+ :register_plugin,
24
+ :load_plugin
23
25
  ].each do |method_name|
24
26
  def_delegator :'RgGen.builder', method_name
25
27
  end
@@ -3,23 +3,28 @@
3
3
  module RgGen
4
4
  module Core
5
5
  class RgGenError < StandardError
6
- def initialize(message, additional_info = nil)
6
+ def initialize(message, location_info = nil, verbose_info = nil)
7
7
  super(message)
8
8
  @error_message = message
9
- @additional_info = additional_info
9
+ @location_info = location_info
10
+ @verbose_info = verbose_info
10
11
  end
11
12
 
12
13
  attr_reader :error_message
13
- attr_reader :additional_info
14
+ attr_reader :location_info
15
+ attr_reader :verbose_info
14
16
 
15
17
  def to_s
16
- additional_info ? "#{super} -- #{additional_info}" : super
18
+ location_info && "#{super} -- #{location_info}" || super
17
19
  end
18
20
  end
19
21
 
20
22
  class BuilderError < RgGenError
21
23
  end
22
24
 
25
+ class PluginError < RgGenError
26
+ end
27
+
23
28
  class RuntimeError < RgGenError
24
29
  end
25
30
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'facets/array/merge'
4
4
  require 'facets/file/ext'
5
- require 'facets/hash/at'
5
+ require 'facets/hash/except' if RUBY_VERSION < '3.0.0'
6
6
  require 'facets/pathname/to_path'
7
7
  require 'facets/module/attr_setter'
8
8
  require 'facets/module/lastname'
@@ -4,7 +4,7 @@ module RgGen
4
4
  module Core
5
5
  class Generator
6
6
  def run(builder, options)
7
- load_setup_file(builder, options[:setup])
7
+ load_plugins(builder, options)
8
8
  load_configuration(builder, options[:configuration])
9
9
  load_register_map(builder, options.register_map_files)
10
10
  write_files(builder, options)
@@ -15,8 +15,8 @@ module RgGen
15
15
  attr_reader :configuration
16
16
  attr_reader :register_map
17
17
 
18
- def load_setup_file(builder, file)
19
- builder.load_setup_file(file)
18
+ def load_plugins(builder, options)
19
+ builder.load_plugins(options[:plugins], options[:no_default_plugins])
20
20
  end
21
21
 
22
22
  def load_configuration(builder, file)
@@ -9,10 +9,22 @@ module RgGen
9
9
  define_proxy_calls(feature, feature.properties)
10
10
  end
11
11
 
12
+ def document_only
13
+ @document_only = true
14
+ end
15
+
16
+ def document_only?
17
+ instance_variable_defined?(:@document_only) && @document_only
18
+ end
19
+
12
20
  def properties
13
21
  features.flat_map(&:properties)
14
22
  end
15
23
 
24
+ def post_build
25
+ features.each(&:post_build)
26
+ end
27
+
16
28
  def verify(scope)
17
29
  features.each { |feature| feature.verify(scope) }
18
30
  children.each { |child| child.verify(scope) } if scope == :all
@@ -79,6 +79,7 @@ module RgGen
79
79
  def post_build(component)
80
80
  exist_no_children?(component) &&
81
81
  raise_no_children_error(component)
82
+ component.post_build
82
83
  component.verify(:component)
83
84
  end
84
85