rggen-core 0.9.0

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