rggen-core 0.9.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 (87) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +46 -0
  3. data/LICENSE +21 -0
  4. data/README.md +46 -0
  5. data/exe/rggen +13 -0
  6. data/lib/rggen/core.rb +101 -0
  7. data/lib/rggen/core/base/component.rb +54 -0
  8. data/lib/rggen/core/base/component_factory.rb +84 -0
  9. data/lib/rggen/core/base/feature.rb +46 -0
  10. data/lib/rggen/core/base/feature_factory.rb +37 -0
  11. data/lib/rggen/core/base/hierarchical_accessors.rb +91 -0
  12. data/lib/rggen/core/base/hierarchical_feature_accessors.rb +83 -0
  13. data/lib/rggen/core/base/internal_struct.rb +21 -0
  14. data/lib/rggen/core/base/shared_context.rb +18 -0
  15. data/lib/rggen/core/builder.rb +13 -0
  16. data/lib/rggen/core/builder/builder.rb +150 -0
  17. data/lib/rggen/core/builder/category.rb +116 -0
  18. data/lib/rggen/core/builder/component_entry.rb +29 -0
  19. data/lib/rggen/core/builder/component_registry.rb +47 -0
  20. data/lib/rggen/core/builder/feature_registry.rb +126 -0
  21. data/lib/rggen/core/builder/input_component_registry.rb +35 -0
  22. data/lib/rggen/core/builder/list_feature_entry.rb +98 -0
  23. data/lib/rggen/core/builder/output_component_registry.rb +10 -0
  24. data/lib/rggen/core/builder/simple_feature_entry.rb +39 -0
  25. data/lib/rggen/core/cli.rb +29 -0
  26. data/lib/rggen/core/configuration.rb +19 -0
  27. data/lib/rggen/core/configuration/component.rb +10 -0
  28. data/lib/rggen/core/configuration/component_factory.rb +19 -0
  29. data/lib/rggen/core/configuration/error.rb +16 -0
  30. data/lib/rggen/core/configuration/feature.rb +13 -0
  31. data/lib/rggen/core/configuration/feature_factory.rb +11 -0
  32. data/lib/rggen/core/configuration/hash_loader.rb +15 -0
  33. data/lib/rggen/core/configuration/json_loader.rb +18 -0
  34. data/lib/rggen/core/configuration/loader.rb +11 -0
  35. data/lib/rggen/core/configuration/ruby_loader.rb +15 -0
  36. data/lib/rggen/core/configuration/yaml_loader.rb +18 -0
  37. data/lib/rggen/core/core_extensions/casecmp.rb +12 -0
  38. data/lib/rggen/core/core_extensions/forwardable.rb +12 -0
  39. data/lib/rggen/core/core_extensions/forwardable_workaround.rb +22 -0
  40. data/lib/rggen/core/core_extensions/object.rb +14 -0
  41. data/lib/rggen/core/dsl.rb +30 -0
  42. data/lib/rggen/core/exceptions.rb +29 -0
  43. data/lib/rggen/core/facets.rb +7 -0
  44. data/lib/rggen/core/generator.rb +51 -0
  45. data/lib/rggen/core/input_base/component.rb +30 -0
  46. data/lib/rggen/core/input_base/component_factory.rb +88 -0
  47. data/lib/rggen/core/input_base/feature.rb +130 -0
  48. data/lib/rggen/core/input_base/feature_factory.rb +80 -0
  49. data/lib/rggen/core/input_base/input_data.rb +98 -0
  50. data/lib/rggen/core/input_base/input_matcher.rb +79 -0
  51. data/lib/rggen/core/input_base/input_value.rb +34 -0
  52. data/lib/rggen/core/input_base/json_loader.rb +16 -0
  53. data/lib/rggen/core/input_base/loader.rb +44 -0
  54. data/lib/rggen/core/input_base/property.rb +76 -0
  55. data/lib/rggen/core/input_base/verifier.rb +41 -0
  56. data/lib/rggen/core/input_base/yaml_loader.rb +34 -0
  57. data/lib/rggen/core/options.rb +181 -0
  58. data/lib/rggen/core/output_base/code_generator.rb +59 -0
  59. data/lib/rggen/core/output_base/component.rb +100 -0
  60. data/lib/rggen/core/output_base/component_factory.rb +35 -0
  61. data/lib/rggen/core/output_base/erb_engine.rb +21 -0
  62. data/lib/rggen/core/output_base/feature.rb +147 -0
  63. data/lib/rggen/core/output_base/feature_factory.rb +13 -0
  64. data/lib/rggen/core/output_base/file_writer.rb +40 -0
  65. data/lib/rggen/core/output_base/template_engine.rb +27 -0
  66. data/lib/rggen/core/printers.rb +53 -0
  67. data/lib/rggen/core/register_map.rb +21 -0
  68. data/lib/rggen/core/register_map/component.rb +20 -0
  69. data/lib/rggen/core/register_map/component_factory.rb +19 -0
  70. data/lib/rggen/core/register_map/error.rb +16 -0
  71. data/lib/rggen/core/register_map/feature.rb +22 -0
  72. data/lib/rggen/core/register_map/feature_factory.rb +11 -0
  73. data/lib/rggen/core/register_map/hash_loader.rb +47 -0
  74. data/lib/rggen/core/register_map/input_data.rb +34 -0
  75. data/lib/rggen/core/register_map/json_loader.rb +18 -0
  76. data/lib/rggen/core/register_map/loader.rb +15 -0
  77. data/lib/rggen/core/register_map/ruby_loader.rb +15 -0
  78. data/lib/rggen/core/register_map/yaml_loader.rb +18 -0
  79. data/lib/rggen/core/utility/attribute_setter.rb +53 -0
  80. data/lib/rggen/core/utility/code_utility.rb +64 -0
  81. data/lib/rggen/core/utility/code_utility/code_block.rb +88 -0
  82. data/lib/rggen/core/utility/code_utility/line.rb +51 -0
  83. data/lib/rggen/core/utility/code_utility/source_file.rb +104 -0
  84. data/lib/rggen/core/utility/code_utility/structure_definition.rb +54 -0
  85. data/lib/rggen/core/utility/regexp_patterns.rb +38 -0
  86. data/lib/rggen/core/version.rb +10 -0
  87. metadata +188 -0
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class ComponentEntry
7
+ Entry = Struct.new(:target, :factory)
8
+
9
+ [:component, :feature].each do |entry_name|
10
+ define_method(entry_name) do |target, factory|
11
+ instance_variable_set("@#{__method__}", Entry.new(target, factory))
12
+ end
13
+ end
14
+
15
+ def feature_registry
16
+ return unless @feature
17
+ @feature_registry ||= FeatureRegistry.new(*@feature.values)
18
+ end
19
+
20
+ def build_factory
21
+ @component.factory.new do |f|
22
+ f.target_component(@component.target)
23
+ f.feature_factories(feature_registry&.build_factories)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class ComponentRegistry
7
+ def initialize(name, builder)
8
+ @name = name
9
+ @builder = builder
10
+ @entries = []
11
+ end
12
+
13
+ def register_component(categories = nil, &block)
14
+ if categories
15
+ Array(categories).each do |category|
16
+ @entries << create_new_entry(category, block)
17
+ end
18
+ else
19
+ @entries << create_new_entry(nil, block)
20
+ end
21
+ end
22
+
23
+ def build_factory
24
+ factories = @entries.map(&:build_factory)
25
+ factories.each_cons(2) { |(f0, f1)| f0.child_factory(f1) }
26
+ root_factory = factories.first
27
+ root_factory.root_factory
28
+ root_factory
29
+ end
30
+
31
+ private
32
+
33
+ def create_new_entry(category, block)
34
+ entry = ComponentEntry.new
35
+ Docile.dsl_eval(entry, category, &block)
36
+ add_feature_registry(category, entry.feature_registry)
37
+ entry
38
+ end
39
+
40
+ def add_feature_registry(category, feature_registry)
41
+ feature_registry || return
42
+ @builder.add_feature_registry(@name, category, feature_registry)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class FeatureRegistry
7
+ def initialize(base_feature, factory)
8
+ @base_feature = base_feature
9
+ @factory = factory
10
+ @feature_entries = {}
11
+ @enabled_features = {}
12
+ end
13
+
14
+ def define_simple_feature(names, context = nil, &body)
15
+ Array(names)
16
+ .each { |name| create_new_entry(:simple, name, context, body) }
17
+ end
18
+
19
+ def define_list_feature(list_names, context = nil, &body)
20
+ Array(list_names)
21
+ .each { |name| create_new_entry(:list, name, context, body) }
22
+ end
23
+
24
+ def define_list_item_feature(list_name, feature_names, context = nil, &body)
25
+ entry = @feature_entries[list_name]
26
+ entry&.match_entry_type?(:list) ||
27
+ (raise BuilderError.new("unknown list feature: #{list_name}"))
28
+ Array(feature_names)
29
+ .each { |name| entry.define_feature(name, context, &body) }
30
+ end
31
+
32
+ def enable(feature_or_list_names, feature_names = nil)
33
+ if feature_names
34
+ @enabled_features[feature_or_list_names]
35
+ &.merge!(Array(feature_names))
36
+ else
37
+ Array(feature_or_list_names).each do |name|
38
+ @enabled_features[name] ||= []
39
+ end
40
+ end
41
+ end
42
+
43
+ def enabled_features(list_name = nil)
44
+ if list_name
45
+ @enabled_features[list_name] || []
46
+ else
47
+ @enabled_features.keys
48
+ end
49
+ end
50
+
51
+ def disable(feature_or_list_names = nil, feature_names = nil)
52
+ if feature_names
53
+ @enabled_features[feature_or_list_names]
54
+ &.delete_if { |key, _| Array(feature_names).include?(key) }
55
+ elsif feature_or_list_names
56
+ Array(feature_or_list_names)
57
+ .each(&@enabled_features.method(:delete))
58
+ else
59
+ @enabled_features.clear
60
+ end
61
+ end
62
+
63
+ def delete(feature_or_list_names = nil, feature_names = nil)
64
+ if feature_names
65
+ @feature_entries[feature_or_list_names]&.delete(feature_names)
66
+ elsif feature_or_list_names
67
+ Array(feature_or_list_names)
68
+ .each(&@feature_entries.method(:delete))
69
+ else
70
+ @feature_entries.clear
71
+ end
72
+ end
73
+
74
+ def simple_feature?(feature_name)
75
+ enabled_feature?(feature_name, :simple)
76
+ end
77
+
78
+ def list_feature?(list_name, feature_name = nil)
79
+ return false unless enabled_feature?(list_name, :list)
80
+ return true unless feature_name
81
+ enabled_list_item_feature?(list_name, feature_name)
82
+ end
83
+
84
+ def feature?(feature_or_list_name, feature_name = nil)
85
+ if feature_name
86
+ list_feature?(feature_or_list_name, feature_name)
87
+ else
88
+ simple_feature?(feature_or_list_name) ||
89
+ list_feature?(feature_or_list_name)
90
+ end
91
+ end
92
+
93
+ def build_factories
94
+ @enabled_features
95
+ .select { |n, _| @feature_entries.key?(n) }
96
+ .map { |n, f| [n, @feature_entries[n].build_factory(f)] }
97
+ .to_h
98
+ end
99
+
100
+ private
101
+
102
+ FEATURE_ENTRIES = {
103
+ simple: SimpleFeatureEntry, list: ListFeatureEntry
104
+ }.freeze
105
+
106
+ def create_new_entry(type, name, context, body)
107
+ entry = FEATURE_ENTRIES[type].new(self, name)
108
+ entry.setup(@base_feature, @factory, context, body)
109
+ @feature_entries[name] = entry
110
+ end
111
+
112
+ def enabled_feature?(name, entry_type)
113
+ return false unless @feature_entries[name]
114
+ &.match_entry_type?(entry_type)
115
+ @enabled_features.key?(name)
116
+ end
117
+
118
+ def enabled_list_item_feature?(list_name, feature_name)
119
+ return false unless @feature_entries[list_name]
120
+ .feature?(feature_name)
121
+ @enabled_features[list_name].include?(feature_name)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class InputComponentRegistry < ComponentRegistry
7
+ def initialize(name, builder)
8
+ super
9
+ @loaders = []
10
+ end
11
+
12
+ attr_setter :base_loader
13
+
14
+ def register_loader(loader)
15
+ @loaders << loader
16
+ end
17
+
18
+ def register_loaders(loaders)
19
+ @loaders.concat(Array(loaders))
20
+ end
21
+
22
+ def define_loader(&body)
23
+ loader = Class.new(@base_loader, &body)
24
+ register_loader(loader)
25
+ end
26
+
27
+ def build_factory
28
+ factory = super
29
+ factory.loaders(@loaders)
30
+ factory
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class ListFeatureEntry
7
+ include Base::SharedContext
8
+
9
+ def initialize(registry, name)
10
+ @registry = registry
11
+ @name = name
12
+ @features = {}
13
+ end
14
+
15
+ attr_reader :registry
16
+ attr_reader :name
17
+
18
+ def setup(base_feature, base_factory, context, body)
19
+ @base_feature = Class.new(base_feature)
20
+ @factory = Class.new(base_factory)
21
+ context && attach_shared_context(context)
22
+ body && Docile.dsl_eval(self, @name, &body)
23
+ end
24
+
25
+ def match_entry_type?(entry_type)
26
+ entry_type == :list
27
+ end
28
+
29
+ def define_factory(&body)
30
+ @factory.class_exec(&body)
31
+ end
32
+
33
+ alias_method :factory, :define_factory
34
+
35
+ def build_factory(enabled_features)
36
+ @factory.new(@name) do |f|
37
+ f.target_features(target_features(enabled_features))
38
+ f.target_feature(@default_feature)
39
+ end
40
+ end
41
+
42
+ def define_base_feature(&body)
43
+ body && @base_feature.class_exec(&body)
44
+ end
45
+
46
+ alias_method :base_feature, :define_base_feature
47
+
48
+ def define_feature(feature_name, context = nil, &body)
49
+ @features[feature_name] ||= Class.new(@base_feature)
50
+ feature = @features[feature_name]
51
+ if context
52
+ feature.method_defined?(:shared_context) && (
53
+ raise BuilderError.new('shared context has already been set')
54
+ )
55
+ feature.attach_context(context)
56
+ end
57
+ body && feature.class_exec(feature_name, &body)
58
+ end
59
+
60
+ alias_method :feature, :define_feature
61
+
62
+ def define_default_feature(&body)
63
+ @default_feature ||= Class.new(@base_feature)
64
+ body && @default_feature.class_exec(&body)
65
+ end
66
+
67
+ alias_method :default_feature, :define_default_feature
68
+
69
+ def delete(features = nil)
70
+ if features
71
+ Array(features).each { |feature| @features.delete(feature) }
72
+ else
73
+ @features.clear
74
+ end
75
+ end
76
+
77
+ def feature?(feature)
78
+ @features.key?(feature)
79
+ end
80
+
81
+ private
82
+
83
+ def attach_shared_context(context)
84
+ [@factory, @base_feature, self].each do |target|
85
+ target.attach_context(context)
86
+ end
87
+ end
88
+
89
+ def target_features(enabled_features)
90
+ enabled_features
91
+ .select { |n| @features.key?(n) }
92
+ .map { |n| [n, @features[n]] }
93
+ .to_h
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class OutputComponentRegistry < ComponentRegistry
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Builder
6
+ class SimpleFeatureEntry
7
+ def initialize(registry, name)
8
+ @registry = registry
9
+ @name = name
10
+ end
11
+
12
+ attr_reader :registry
13
+ attr_reader :name
14
+
15
+ def setup(base_feature, factory, context, body)
16
+ @feature = define_feature(base_feature, context, body)
17
+ @factory = factory
18
+ end
19
+
20
+ def match_entry_type?(entry_type)
21
+ entry_type == :simple
22
+ end
23
+
24
+ def build_factory(_enabled_features)
25
+ @factory.new(@name) { |f| f.target_feature(@feature) }
26
+ end
27
+
28
+ private
29
+
30
+ def define_feature(base, context, body)
31
+ feature = Class.new(base)
32
+ context && feature.attach_context(context)
33
+ body && feature.class_exec(@name, &body)
34
+ feature
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ class CLI
6
+ def initialize(builder = nil)
7
+ RgGen.builder(builder || Builder.create)
8
+ end
9
+
10
+ def run(args)
11
+ options = parse_options(args)
12
+ builder = RgGen.builder
13
+ runner(options).run(builder, options)
14
+ end
15
+
16
+ private
17
+
18
+ def parse_options(args)
19
+ options = Options.new
20
+ options.parse(args)
21
+ options
22
+ end
23
+
24
+ def runner(options)
25
+ options[:runner] || Generator.new
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Configuration
6
+ def self.setup(builder)
7
+ builder.input_component_registry(:configuration) do
8
+ register_component do
9
+ component Component, ComponentFactory
10
+ feature Feature, FeatureFactory
11
+ end
12
+
13
+ base_loader Loader
14
+ register_loaders [RubyLoader, JSONLoader, YAMLLoader]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Configuration
6
+ class Component < InputBase::Component
7
+ end
8
+ end
9
+ end
10
+ end