|
9 | 9 | # syntax could work... |
10 | 10 | class Empirical::AttrProcessor < Empirical::BaseProcessor |
11 | 11 | ATTR_METHODS = Set[:attr_accessor, :attr_reader, :attr_writer].freeze |
| 12 | + VISIBILITY_METHODS = Set[:private, :protected, :public].freeze |
12 | 13 |
|
13 | 14 | def visit_call_node(node) |
14 | | - if ATTR_METHODS.include?(node.name) |
| 15 | + # Check if this is a visibility modifier wrapping an attr call, we need it for oua generated methods |
| 16 | + if VISIBILITY_METHODS.include?(node.name) && node.arguments |
| 17 | + arg = node.arguments.arguments.first |
| 18 | + if arg.is_a?(Prism::CallNode) && ATTR_METHODS.include?(arg.name) |
| 19 | + visit_attr_call_node(arg, visibility: node.name) |
| 20 | + end |
| 21 | + # TODO: We don't call super because we have effectively handled the modifier ourselves |
| 22 | + # ... though the original methods visibility is now not set correct? |
| 23 | + return |
| 24 | + elsif ATTR_METHODS.include?(node.name) |
15 | 25 | visit_attr_call_node(node) |
16 | 26 | end |
17 | 27 |
|
18 | 28 | super |
19 | 29 | end |
20 | 30 |
|
21 | | - def visit_attr_call_node(node) |
| 31 | + def visit_attr_call_node(node, visibility: nil) |
22 | 32 | # TODO: improve errors, as per `fun` |
23 | 33 | raise SyntaxError unless node.arguments |
24 | 34 | raise SyntaxError if node.receiver |
@@ -62,9 +72,9 @@ def visit_attr_call_node(node) |
62 | 72 | # TODO: here we check on read for attr_readre and on write for writer/accessor, makes sense? |
63 | 73 | case node.name |
64 | 74 | when :attr_reader |
65 | | - post_end_buffer << typed_getter(attr_name, attr_type_ident) |
| 75 | + post_end_buffer << typed_getter(attr_name, attr_type_ident, visibility) |
66 | 76 | when :attr_writer, :attr_accessor |
67 | | - post_end_buffer << typed_setter(attr_name, attr_type_ident) |
| 77 | + post_end_buffer << typed_setter(attr_name, attr_type_ident, visibility) |
68 | 78 | end |
69 | 79 | end |
70 | 80 |
|
@@ -94,12 +104,16 @@ def extract_typed_attrs_from_hash(elements) |
94 | 104 | end |
95 | 105 |
|
96 | 106 | # TODO: readability! |
97 | | - def typed_getter(attr_name, type_ident) |
98 | | - "alias_method(:__original_#{attr_name}, :#{attr_name});def #{attr_name};__value = __original_#{attr_name};raise(::Empirical::TypeError.attr_type_error(name: '#{attr_name}', value: __value, expected: ::Empirical::TypeStore::#{type_ident}, attr_type: 'reader', context: self)) unless ::Empirical::TypeStore::#{type_ident} === __value;__value;end" |
| 107 | + def typed_getter(attr_name, type_ident, visibility = nil) |
| 108 | + code = "alias_method(:__original_#{attr_name}, :#{attr_name});def #{attr_name};__value = __original_#{attr_name};raise(::Empirical::TypeError.attr_type_error(name: '#{attr_name}', value: __value, expected: ::Empirical::TypeStore::#{type_ident}, attr_type: 'reader', context: self)) unless ::Empirical::TypeStore::#{type_ident} === __value;__value;end" |
| 109 | + code += ";#{visibility} :#{attr_name}" if visibility |
| 110 | + code |
99 | 111 | end |
100 | 112 |
|
101 | | - def typed_setter(attr_name, type_ident) |
102 | | - "alias_method(:__original_#{attr_name}=, :#{attr_name}=);def #{attr_name}=(value);raise(::Empirical::TypeError.attr_type_error(name: '#{attr_name}', value: value, expected: ::Empirical::TypeStore::#{type_ident}, attr_type: 'writer', context: self)) unless ::Empirical::TypeStore::#{type_ident} === value;send(:__original_#{attr_name}=, value);end" |
| 113 | + def typed_setter(attr_name, type_ident, visibility = nil) |
| 114 | + code = "alias_method(:__original_#{attr_name}=, :#{attr_name}=);def #{attr_name}=(value);raise(::Empirical::TypeError.attr_type_error(name: '#{attr_name}', value: value, expected: ::Empirical::TypeStore::#{type_ident}, attr_type: 'writer', context: self)) unless ::Empirical::TypeStore::#{type_ident} === value;send(:__original_#{attr_name}=, value);end" |
| 115 | + code += ";#{visibility} :#{attr_name}=" if visibility |
| 116 | + code |
103 | 117 | end |
104 | 118 |
|
105 | 119 | # TODO: duplication |
|
0 commit comments