Module: RemindMe::Utils::HashASTManipulations
- Included in:
- Reminder::BaseReminder
- Defined in:
- lib/remind_me/utils/hash_ast_manipulations.rb
Instance Method Summary collapse
-
#apply_to_hash_with(key_values) ⇒ Object
Will look for string/symbol keys with specified names in the comment, and if all are found, will return true.
- #ast_hash_pair(hash_ast, key_value) ⇒ Object
- #children_of_type(reminder_comment_ast, type) ⇒ Object
- #create_hash_value_accessor_method(key) ⇒ Object
- #create_reminder_from_ast(reminder_comment_ast, source_location) ⇒ Object
- #hash_ast_pair_value(ast_pair) ⇒ Object
- #hash_ast_pair_value_type(ast_pair) ⇒ Object
- #key_present?(reminder_comment_ast, key_value) ⇒ Boolean
- #singleton_method_defined?(method_name) ⇒ Boolean
-
#valid_hash_ast_key?(ast_pair, key_value) ⇒ Boolean
key is either a symbol or string.
- #valid_hash_ast_value?(ast_pair, allowed_types) ⇒ Boolean
- #validate_hash_ast(key:, value_types:, **options) ⇒ Object
Instance Method Details
#apply_to_hash_with(key_values) ⇒ Object
Will look for string/symbol keys with specified names in the comment, and if all are found, will return true
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 10 def apply_to_hash_with(key_values) # Method for determining if we should consider given reminder for this AST define_singleton_method('applicable_to_ast?') do |ast| ast.type == :hash && key_values.all? { |key_value| key_present?(ast, key_value) } end # Building a Reminder from AST, creating invalid one if any of validations returns any non-nil value define_singleton_method('build_from') do |reminder_comment_ast, source_location| create_reminder_from_ast(reminder_comment_ast, source_location) end key_values.each do |key| validate_hash_ast(key: key, value_types: %i[sym str]) end end |
#ast_hash_pair(hash_ast, key_value) ⇒ Object
88 89 90 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 88 def ast_hash_pair(hash_ast, key_value) children_of_type(hash_ast, :pair).find { |pair| valid_hash_ast_key?(pair, key_value) } end |
#children_of_type(reminder_comment_ast, type) ⇒ Object
96 97 98 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 96 def children_of_type(reminder_comment_ast, type) reminder_comment_ast.children.select { |child| child.type.to_s == type.to_s } end |
#create_hash_value_accessor_method(key) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 69 def create_hash_value_accessor_method(key) return if method_defined?("hash_#{key}") send(:define_method, "hash_#{key}") do comment_ast = instance_variable_get('@reminder_comment_ast') value = self.class.hash_ast_pair_value(self.class.ast_hash_pair(comment_ast, key)) default_values = self.class.instance_variable_get('@hash_ast_default_values') if (value.nil? || value == '') && default_values.key?(key) default_values[key] else value end end end |
#create_reminder_from_ast(reminder_comment_ast, source_location) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 50 def create_reminder_from_ast(reminder_comment_ast, source_location) # We first perform AST validation ast_validation_errors = singleton_methods.select { |method| method.to_s.start_with?('validate_hash_ast_') } .map { |method| send(method, reminder_comment_ast, source_location) } .compact if ast_validation_errors.empty? # AST looks good, now we perform reminder-specific validations reminder = new(reminder_comment_ast, source_location) validation_errors = reminder.validation_errors if validation_errors.empty? reminder else RemindMe::Reminder::InvalidReminder.new(source_location, validation_errors.join(';')) end else RemindMe::Reminder::InvalidReminder.new(source_location, ast_validation_errors.join(';')) end end |
#hash_ast_pair_value(ast_pair) ⇒ Object
115 116 117 118 119 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 115 def hash_ast_pair_value(ast_pair) return nil if ast_pair.nil? || ast_pair.children.nil? || ast_pair.children.size != 2 ast_pair.children[1].to_a.first end |
#hash_ast_pair_value_type(ast_pair) ⇒ Object
111 112 113 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 111 def hash_ast_pair_value_type(ast_pair) ast_pair.children[1].type end |
#key_present?(reminder_comment_ast, key_value) ⇒ Boolean
92 93 94 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 92 def key_present?(reminder_comment_ast, key_value) children_of_type(reminder_comment_ast, :pair).any? { |pair| valid_hash_ast_key?(pair, key_value) } end |
#singleton_method_defined?(method_name) ⇒ Boolean
84 85 86 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 84 def singleton_method_defined?(method_name) singleton_methods.any? { |method| method.to_s == method_name } end |
#valid_hash_ast_key?(ast_pair, key_value) ⇒ Boolean
key is either a symbol or string
101 102 103 104 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 101 def valid_hash_ast_key?(ast_pair, key_value) key = ast_pair.children.first %i[sym str].include?(key.type) && key_value.to_s == key.to_a.first.to_s end |
#valid_hash_ast_value?(ast_pair, allowed_types) ⇒ Boolean
106 107 108 109 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 106 def valid_hash_ast_value?(ast_pair, allowed_types) value = ast_pair.children[1] allowed_types.include?(value.type) end |
#validate_hash_ast(key:, value_types:, **options) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/remind_me/utils/hash_ast_manipulations.rb', line 24 def validate_hash_ast(key:, value_types:, **) @hash_ast_default_values ||= {} @hash_ast_default_values[key] = [:default_value] if .key?(:default_value) create_hash_value_accessor_method(key) define_singleton_method("validate_hash_ast_#{key}") do |ast, source_location| return "REMIND_ME comment in #{source_location} is not a Hash" unless ast.type == :hash pair = ast_hash_pair(ast, key) # Valid pair was not found... if pair.nil? # ... and we don't have default value set for it unless @hash_ast_default_values.key?(key) "REMIND_ME comment in #{source_location}: value for '#{key}' could not be found, key needs to be "\ "either String or Symbol. If not set 'default_value' can be used, but that one was not given as well" end # Pair was found... else # ... but it does not have proper value type unless valid_hash_ast_value?(pair, value_types) "REMIND_ME comment in #{source_location}: value under specified key '#{key}' does not have allowed "\ "type (it has '#{hash_ast_pair_value_type(pair)}'), allowed types are #{value_types}" end end end end |