rggen-core 0.21.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
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