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,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class Feature < Base::Feature
7
+ include Utility::RegexpPatterns
8
+
9
+ class << self
10
+ def property(name, **options, &body)
11
+ Property.define(self, name, **options, &body)
12
+ properties.include?(name) || properties << name
13
+ end
14
+
15
+ alias_method :field, :property
16
+
17
+ def properties
18
+ @properties ||= []
19
+ end
20
+
21
+ def ignore_empty_value(value = nil)
22
+ @ignore_empty_value = value unless value.nil?
23
+ @ignore_empty_value
24
+ end
25
+
26
+ def ignore_empty_value?
27
+ @ignore_empty_value.nil? || @ignore_empty_value
28
+ end
29
+
30
+ def build(&block)
31
+ @builders ||= []
32
+ @builders << block
33
+ end
34
+
35
+ attr_reader :builders
36
+
37
+ def active_feature?
38
+ !passive_feature?
39
+ end
40
+
41
+ def passive_feature?
42
+ builders.nil?
43
+ end
44
+
45
+ def input_pattern(pattern_or_patterns, **options, &converter)
46
+ @input_matcher =
47
+ InputMatcher.new(pattern_or_patterns, options, &converter)
48
+ end
49
+
50
+ attr_reader :input_matcher
51
+
52
+ def verify(scope, &block)
53
+ @verifiers ||= {}
54
+ (@verifiers[scope] ||= []) << Verifier.new(&block)
55
+ end
56
+
57
+ attr_reader :verifiers
58
+
59
+ def inherited(subclass)
60
+ super
61
+ export_instance_variable(:@properties, subclass, &:dup)
62
+ export_instance_variable(:@ignore_empty_value, subclass)
63
+ export_instance_variable(:@builders, subclass, &:dup)
64
+ export_instance_variable(:@input_matcher, subclass)
65
+ export_verifiers(subclass) if @verifiers
66
+ end
67
+
68
+ private
69
+
70
+ def export_verifiers(subclass)
71
+ copied_verifiers =
72
+ @verifiers.map { |scope, blocks| [scope, blocks.dup] }.to_h
73
+ subclass.instance_variable_set(:@verifiers, copied_verifiers)
74
+ end
75
+ end
76
+
77
+ delegate_to_class [
78
+ :properties, :active_feature?, :passive_feature?, :ignore_empty_value?
79
+ ]
80
+
81
+ def build(*args)
82
+ self.class.builders && do_build(args)
83
+ end
84
+
85
+ def verify(scope)
86
+ verified?(scope) || do_verify(scope)
87
+ end
88
+
89
+ private
90
+
91
+ def do_build(args)
92
+ @position = args.last.position
93
+ args = [*args[0..-2], args.last.value]
94
+ match_automatically? && match_pattern(args.last)
95
+ Array(self.class.builders)
96
+ .each { |builder| instance_exec(*args, &builder) }
97
+ end
98
+
99
+ attr_reader :position
100
+
101
+ def match_automatically?
102
+ matcher = self.class.input_matcher
103
+ matcher&.match_automatically?
104
+ end
105
+
106
+ def match_pattern(rhs)
107
+ matcher = self.class.input_matcher
108
+ @match_data, @match_index = matcher&.match(rhs)
109
+ end
110
+
111
+ attr_reader :match_data
112
+ attr_reader :match_index
113
+
114
+ def pattern_matched?
115
+ !match_data.nil?
116
+ end
117
+
118
+ def verified?(scope)
119
+ @verified && @verified[scope]
120
+ end
121
+
122
+ def do_verify(scope)
123
+ Array(self.class.verifiers&.at(scope))
124
+ .each { |verifier| verifier.verify(self) }
125
+ (@verified ||= {})[scope] = true
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class FeatureFactory < Base::FeatureFactory
7
+ class << self
8
+ def convert_value(&block)
9
+ @value_converter = block
10
+ end
11
+
12
+ attr_reader :value_converter
13
+
14
+ def default_value(&block)
15
+ @default_value = block if block_given?
16
+ @default_value
17
+ end
18
+ end
19
+
20
+ def create(component, *args)
21
+ input_value = preprocess(args.last)
22
+ create_feature(component, *args[0..-2], input_value) do |feature|
23
+ build_feature(feature, input_value)
24
+ feature.verify(:feature)
25
+ end
26
+ end
27
+
28
+ def active_feature_factory?
29
+ !passive_feature_factory?
30
+ end
31
+
32
+ def passive_feature_factory?
33
+ @target_features.nil? && @target_feature.passive_feature?
34
+ end
35
+
36
+ private
37
+
38
+ def preprocess(input_value)
39
+ converted_value =
40
+ active_feature_factory? && convert_value(input_value)
41
+ converted_value || input_value
42
+ end
43
+
44
+ def convert_value(input_value)
45
+ new_value =
46
+ if input_value.empty_value?
47
+ evaluate_defalt_value(input_value.position)
48
+ else
49
+ convert(input_value.value, input_value.position)
50
+ end
51
+ new_value && InputValue.new(new_value, input_value.position)
52
+ end
53
+
54
+ def evaluate_defalt_value(position)
55
+ block = self.class.default_value
56
+ block && instance_exec(position, &block)
57
+ end
58
+
59
+ def convert(value, position)
60
+ block = self.class.value_converter
61
+ block && instance_exec(value, position, &block)
62
+ end
63
+
64
+ def build_feature(feature, input_value)
65
+ build?(feature, input_value) && feature.build(input_value)
66
+ end
67
+
68
+ def build?(feature, input_value)
69
+ active_feature_factory? &&
70
+ input_value.available? &&
71
+ !ignore_empty_value?(feature, input_value)
72
+ end
73
+
74
+ def ignore_empty_value?(feature, input_value)
75
+ feature.ignore_empty_value? && input_value.empty_value?
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class InputData
7
+ def initialize(valid_value_lists)
8
+ @valid_value_lists = valid_value_lists
9
+ @values = Hash.new(NAValue)
10
+ @children = []
11
+ define_setter_methods
12
+ block_given? && yield(self)
13
+ end
14
+
15
+ def value(value_name, value, position = nil)
16
+ symbolized_name = value_name.to_sym
17
+ return unless valid_value?(symbolized_name)
18
+ @values[symbolized_name] =
19
+ case value
20
+ when InputValue
21
+ value
22
+ else
23
+ InputValue.new(value, position)
24
+ end
25
+ end
26
+
27
+ def []=(value_name, position = nil, value)
28
+ value(value_name, value, position)
29
+ end
30
+
31
+ def [](value_name)
32
+ @values[value_name]
33
+ end
34
+
35
+ def values(value_list = nil, position = nil)
36
+ value_list && Hash(value_list).each { |n, v| value(n, v, position) }
37
+ @values
38
+ end
39
+
40
+ attr_reader :children
41
+
42
+ def child(value_list = nil, &block)
43
+ create_child_data do |child_data|
44
+ child_data.build_by_block(block)
45
+ child_data.values(value_list)
46
+ @children << child_data
47
+ end
48
+ end
49
+
50
+ def load_file(file)
51
+ build_by_block(
52
+ instance_eval("-> { #{File.binread(file)} }", file, 1)
53
+ )
54
+ end
55
+
56
+ private
57
+
58
+ def valid_value?(value_name)
59
+ @valid_value_lists.first.include?(value_name)
60
+ end
61
+
62
+ def define_setter_methods
63
+ @valid_value_lists.first.each(&method(:define_setter_method))
64
+ end
65
+
66
+ def define_setter_method(value_name)
67
+ define_singleton_method(value_name) do |value, position = nil|
68
+ value_setter(value_name, value, position)
69
+ end
70
+ end
71
+
72
+ def value_setter(value_name, value, position)
73
+ position ||= position_from_caller
74
+ value(value_name, value, position)
75
+ end
76
+
77
+ def position_from_caller
78
+ locations = caller_locations(3, 2)
79
+ locations[0].path.include?('docile') ? locations[1] : locations[0]
80
+ end
81
+
82
+ def create_child_data(&block)
83
+ child_data_class.new(@valid_value_lists[1..-1], &block)
84
+ end
85
+
86
+ def child_data_class
87
+ InputData
88
+ end
89
+
90
+ protected
91
+
92
+ def build_by_block(block)
93
+ block && Docile.dsl_eval(self, &block)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class InputMatcher
7
+ def initialize(pattern_or_patterns, options, &converter)
8
+ @options = options
9
+ @converter = converter
10
+ @patterns = format_patterns(pattern_or_patterns)
11
+ end
12
+
13
+ def match(rhs)
14
+ rhs = rhs.to_s
15
+ rhs = delete_blanks(rhs) if ignore_blanks?
16
+ match_patterns(rhs)
17
+ end
18
+
19
+ def match_automatically?
20
+ @options.fetch(:match_automatically, true)
21
+ end
22
+
23
+ private
24
+
25
+ def format_patterns(patterns)
26
+ if @options.fetch(:match_wholly, true)
27
+ patterns_hash(patterns)
28
+ .map { |i, pattern| [i, /\A#{pattern}\z/] }
29
+ .to_h
30
+ else
31
+ patterns_hash(patterns)
32
+ end
33
+ end
34
+
35
+ def patterns_hash(patterns)
36
+ if patterns.is_a?(Hash)
37
+ patterns
38
+ else
39
+ Array(patterns)
40
+ .map.with_index { |pattern, i| [i, pattern] }
41
+ .to_h
42
+ end
43
+ end
44
+
45
+ def ignore_blanks?
46
+ @options.fetch(:ignore_blanks, true)
47
+ end
48
+
49
+ DELETE_BLANK_PATTERN =
50
+ Regexp.union(
51
+ /(?<=\w)[[:blank:]]+(?=[[:punct:]&&[^_]])/,
52
+ /(?<=[[:punct:]&&[^_]])[[:blank:]]+(?=\w)/
53
+ ).freeze
54
+
55
+ COMPRESS_BLANK_PATTERN = /[[:blank:]]+/.freeze
56
+
57
+ def delete_blanks(rhs)
58
+ rhs
59
+ .strip
60
+ .gsub(DELETE_BLANK_PATTERN, '')
61
+ .gsub(COMPRESS_BLANK_PATTERN, ' ')
62
+ end
63
+
64
+ def match_patterns(rhs)
65
+ match_data, index =
66
+ @patterns
67
+ .map { |i, pattern| pattern.match(rhs) { |m| [m, i] } }
68
+ .compact
69
+ .max { |m| m[0].length }
70
+ match_data && [convert_match_data(match_data), index]
71
+ end
72
+
73
+ def convert_match_data(match_data)
74
+ @converter&.call(match_data) || match_data
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class InputValue
7
+ def initialize(value, position)
8
+ @value = (value.is_a?(String) && value.strip) || value
9
+ @position = position
10
+ end
11
+
12
+ attr_accessor :value
13
+ attr_reader :position
14
+
15
+ def empty_value?
16
+ return true if @value.nil?
17
+ return true if @value.respond_to?(:empty?) && @value.empty?
18
+ false
19
+ end
20
+
21
+ def available?
22
+ true
23
+ end
24
+ end
25
+
26
+ NAValue = InputValue.new(nil, nil).instance_eval do
27
+ def available?
28
+ false
29
+ end
30
+ freeze
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ module JSONLoader
7
+ private
8
+
9
+ def load_json(file)
10
+ json = File.binread(file)
11
+ JSON.parse(json, symbolize_names: true)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class Loader
7
+ class << self
8
+ def support_types(types)
9
+ @support_types = types.map(&:to_sym)
10
+ end
11
+
12
+ def support?(file)
13
+ file_ext = File.ext(file).to_sym
14
+ @support_types.any? { |type| type.casecmp?(file_ext) }
15
+ end
16
+
17
+ def load_file(file, input_data, valid_value_list)
18
+ new(input_data, valid_value_list).load_file(file)
19
+ end
20
+ end
21
+
22
+ def initialize(input_data, valid_value_lists)
23
+ @input_data = input_data
24
+ @valid_value_lists = valid_value_lists
25
+ end
26
+
27
+ def load_file(file)
28
+ File.readable?(file) || (
29
+ raise Core::LoadError.new('cannot load such file', file)
30
+ )
31
+ format(read_file(file), file)
32
+ end
33
+
34
+ private
35
+
36
+ def format(_read_data, _file)
37
+ end
38
+
39
+ attr_reader :input_data
40
+ attr_reader :valid_value_lists
41
+ end
42
+ end
43
+ end
44
+ end