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.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/LICENSE +21 -0
- data/README.md +46 -0
- data/exe/rggen +13 -0
- data/lib/rggen/core.rb +101 -0
- data/lib/rggen/core/base/component.rb +54 -0
- data/lib/rggen/core/base/component_factory.rb +84 -0
- data/lib/rggen/core/base/feature.rb +46 -0
- data/lib/rggen/core/base/feature_factory.rb +37 -0
- data/lib/rggen/core/base/hierarchical_accessors.rb +91 -0
- data/lib/rggen/core/base/hierarchical_feature_accessors.rb +83 -0
- data/lib/rggen/core/base/internal_struct.rb +21 -0
- data/lib/rggen/core/base/shared_context.rb +18 -0
- data/lib/rggen/core/builder.rb +13 -0
- data/lib/rggen/core/builder/builder.rb +150 -0
- data/lib/rggen/core/builder/category.rb +116 -0
- data/lib/rggen/core/builder/component_entry.rb +29 -0
- data/lib/rggen/core/builder/component_registry.rb +47 -0
- data/lib/rggen/core/builder/feature_registry.rb +126 -0
- data/lib/rggen/core/builder/input_component_registry.rb +35 -0
- data/lib/rggen/core/builder/list_feature_entry.rb +98 -0
- data/lib/rggen/core/builder/output_component_registry.rb +10 -0
- data/lib/rggen/core/builder/simple_feature_entry.rb +39 -0
- data/lib/rggen/core/cli.rb +29 -0
- data/lib/rggen/core/configuration.rb +19 -0
- data/lib/rggen/core/configuration/component.rb +10 -0
- data/lib/rggen/core/configuration/component_factory.rb +19 -0
- data/lib/rggen/core/configuration/error.rb +16 -0
- data/lib/rggen/core/configuration/feature.rb +13 -0
- data/lib/rggen/core/configuration/feature_factory.rb +11 -0
- data/lib/rggen/core/configuration/hash_loader.rb +15 -0
- data/lib/rggen/core/configuration/json_loader.rb +18 -0
- data/lib/rggen/core/configuration/loader.rb +11 -0
- data/lib/rggen/core/configuration/ruby_loader.rb +15 -0
- data/lib/rggen/core/configuration/yaml_loader.rb +18 -0
- data/lib/rggen/core/core_extensions/casecmp.rb +12 -0
- data/lib/rggen/core/core_extensions/forwardable.rb +12 -0
- data/lib/rggen/core/core_extensions/forwardable_workaround.rb +22 -0
- data/lib/rggen/core/core_extensions/object.rb +14 -0
- data/lib/rggen/core/dsl.rb +30 -0
- data/lib/rggen/core/exceptions.rb +29 -0
- data/lib/rggen/core/facets.rb +7 -0
- data/lib/rggen/core/generator.rb +51 -0
- data/lib/rggen/core/input_base/component.rb +30 -0
- data/lib/rggen/core/input_base/component_factory.rb +88 -0
- data/lib/rggen/core/input_base/feature.rb +130 -0
- data/lib/rggen/core/input_base/feature_factory.rb +80 -0
- data/lib/rggen/core/input_base/input_data.rb +98 -0
- data/lib/rggen/core/input_base/input_matcher.rb +79 -0
- data/lib/rggen/core/input_base/input_value.rb +34 -0
- data/lib/rggen/core/input_base/json_loader.rb +16 -0
- data/lib/rggen/core/input_base/loader.rb +44 -0
- data/lib/rggen/core/input_base/property.rb +76 -0
- data/lib/rggen/core/input_base/verifier.rb +41 -0
- data/lib/rggen/core/input_base/yaml_loader.rb +34 -0
- data/lib/rggen/core/options.rb +181 -0
- data/lib/rggen/core/output_base/code_generator.rb +59 -0
- data/lib/rggen/core/output_base/component.rb +100 -0
- data/lib/rggen/core/output_base/component_factory.rb +35 -0
- data/lib/rggen/core/output_base/erb_engine.rb +21 -0
- data/lib/rggen/core/output_base/feature.rb +147 -0
- data/lib/rggen/core/output_base/feature_factory.rb +13 -0
- data/lib/rggen/core/output_base/file_writer.rb +40 -0
- data/lib/rggen/core/output_base/template_engine.rb +27 -0
- data/lib/rggen/core/printers.rb +53 -0
- data/lib/rggen/core/register_map.rb +21 -0
- data/lib/rggen/core/register_map/component.rb +20 -0
- data/lib/rggen/core/register_map/component_factory.rb +19 -0
- data/lib/rggen/core/register_map/error.rb +16 -0
- data/lib/rggen/core/register_map/feature.rb +22 -0
- data/lib/rggen/core/register_map/feature_factory.rb +11 -0
- data/lib/rggen/core/register_map/hash_loader.rb +47 -0
- data/lib/rggen/core/register_map/input_data.rb +34 -0
- data/lib/rggen/core/register_map/json_loader.rb +18 -0
- data/lib/rggen/core/register_map/loader.rb +15 -0
- data/lib/rggen/core/register_map/ruby_loader.rb +15 -0
- data/lib/rggen/core/register_map/yaml_loader.rb +18 -0
- data/lib/rggen/core/utility/attribute_setter.rb +53 -0
- data/lib/rggen/core/utility/code_utility.rb +64 -0
- data/lib/rggen/core/utility/code_utility/code_block.rb +88 -0
- data/lib/rggen/core/utility/code_utility/line.rb +51 -0
- data/lib/rggen/core/utility/code_utility/source_file.rb +104 -0
- data/lib/rggen/core/utility/code_utility/structure_definition.rb +54 -0
- data/lib/rggen/core/utility/regexp_patterns.rb +38 -0
- data/lib/rggen/core/version.rb +10 -0
- 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,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
|