Module: Ryac::Pipeline::RenamePatcher
- Included in:
- AttrDeclShorten, ConstantAliaser, MethodRenamer, VariableRenamer
- Defined in:
- lib/ryac/pipeline/rename_patcher.rb,
sig/ryac/pipeline/rename_patcher.rbs
Overview
Shared infrastructure for L2-L5 rename pipeline stages. Each stage includes this module and implements its own collect_patches.
Defined Under Namespace
Modules: _NodeWithNameLoc
Instance Method Summary collapse
-
#patch_assoc(node, patches, rename_map, keyword_arg: false) ⇒ Object
The return value is only ever compared against :skip_children; a record-alias union here sends typeprof's solver into unbounded re-propagation during self-hosting, so it stays untyped.
- #patch_block_param_node(block, param_names, patches) ⇒ void
- #patch_block_params(node, patches, block_param_names_map) ⇒ void
- #patch_def_params(node, patches, analysis, param_names_key) ⇒ void
- #patch_for_node(node, patches, analysis, mangled_key) ⇒ void
- #patch_keyword_hash(node, patches, rename_map) {|arg0| ... } ⇒ void
- #patch_keyword_params(keywords, param_names, patches) ⇒ void
- #patch_keyword_rest(keyword_rest, param_names, patches) ⇒ void
- #patch_multi_target_params(node, param_names, patches) ⇒ void
-
#patch_named_param(name, name_loc, param_names, patches) ⇒ void
Shared tail of the rest/**rest/&block patchers: Prism types their name_loc as nullable, but a named parameter always carries one.
- #patch_optional_params(optionals, param_names, patches) ⇒ void
- #patch_post_params(posts, param_names, patches) ⇒ void
- #patch_required_params(requireds, param_names, patches) ⇒ void
- #patch_rest_param(rest, param_names, patches) ⇒ void
- #patch_variable(node, patches, rename_map) ⇒ void
- #patch_variable_name_only(node, patches, rename_map) ⇒ void
-
#prism_location_key(node) ⇒ location_key
Same key the analysis stored the rename under.
- #walk_prism(node) {|arg0| ... } ⇒ void
Instance Method Details
#patch_assoc(node, patches, rename_map, keyword_arg: false) ⇒ Object
The return value is only ever compared against :skip_children; a record-alias union here sends typeprof's solver into unbounded re-propagation during self-hosting, so it stays untyped.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'sig/ryac/pipeline/rename_patcher.rbs', line 34 def patch_assoc(node, patches, rename_map, keyword_arg: false) key_node = node.key val_node = node.value return unless key_node.is_a?(Prism::SymbolNode) return unless key_node.value.to_s.match?(/\A[a-zA-Z_][a-zA-Z0-9_]*\z/) original_key = key_node.value.to_s renamed_key = rename_map[prism_location_key(key_node)] if val_node.is_a?(Prism::ImplicitNode) inner = val_node.value if inner.is_a?(Prism::LocalVariableReadNode) mangled_var = rename_map[prism_location_key(inner)] || inner.name.to_s key_name = keyword_arg ? (renamed_key || original_key) : original_key if key_name == mangled_var if key_name != original_key patches << { start: key_node.location.start_offset, end: val_node.location.end_offset, replacement: "#{key_name}:" } end else sep = mangled_var.start_with?(':') ? ': ' : ':' patches << { start: key_node.location.start_offset, end: val_node.location.end_offset, replacement: "#{key_name}#{sep}#{mangled_var}" } end else if keyword_arg && renamed_key patches << { start: key_node.location.start_offset, end: val_node.location.end_offset, replacement: "#{renamed_key}:" } end end return :skip_children end key_name = renamed_key || original_key if val_node.is_a?(Prism::LocalVariableReadNode) mangled_var = rename_map[prism_location_key(val_node)] || val_node.name.to_s if key_name == mangled_var patches << { start: key_node.location.start_offset, end: val_node.location.end_offset, replacement: "#{key_name}:" } return :skip_children end end if renamed_key loc = key_node.location suffix = loc.slice.end_with?(':') ? ':' : '' patches << { start: loc.start_offset, end: loc.end_offset, replacement: "#{renamed_key}#{suffix}" } end end |
#patch_block_param_node(block, param_names, patches) ⇒ void
This method returns an undefined value.
152 153 154 155 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 152 def patch_block_param_node(block, param_names, patches) return unless block.is_a?(Prism::BlockParameterNode) && block.name patch_named_param(block.name, block.name_loc, param_names, patches) end |
#patch_block_params(node, patches, block_param_names_map) ⇒ void
This method returns an undefined value.
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 157 def patch_block_params(node, patches, block_param_names_map) return unless node.block.is_a?(Prism::BlockNode) block = node.block return unless block.parameters.is_a?(Prism::BlockParametersNode) key = prism_location_key(node) param_map = block_param_names_map[key] return unless param_map mangled_values = param_map.values block_params = block.parameters.parameters has_non_required = block_params && ( block_params.optionals&.any? || block_params.rest || block_params.posts&.any? || block_params.keywords&.any? || block_params.keyword_rest || block_params.block ) if mangled_values.any? { |v| v.match?(/^_\d+$/) } && !has_non_required bp_loc = block.parameters.location patches << { start: bp_loc.start_offset, end: bp_loc.end_offset, replacement: '' } return end block_params = block.parameters.parameters return unless block_params patch_required_params(block_params.requireds, param_map, patches) patch_optional_params(block_params.optionals, param_map, patches) patch_rest_param(block_params.rest, param_map, patches) patch_post_params(block_params.posts, param_map, patches) patch_keyword_params(block_params.keywords, param_map, patches) patch_keyword_rest(block_params.keyword_rest, param_map, patches) patch_block_param_node(block_params.block, param_map, patches) end |
#patch_def_params(node, patches, analysis, param_names_key) ⇒ void
This method returns an undefined value.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 48 def patch_def_params(node, patches, analysis, param_names_key) return unless node.parameters syntax_key = AstUtils.line_col_key(node) data = analysis.syntax_data[syntax_key] return unless data # any? rather than empty?: `empty?` on a receiver TypeProf can prove # is a Hash gets rewritten to `=={}` — but only when it can prove it, # and whether it can differs between the original and the minified # text. Self-hosting then never reaches a fixed point. `any?` has no # such rewrite. param_names = data[param_names_key] || {} #: Hash[Symbol, String] return unless param_names.any? params = node.parameters patch_required_params(params.requireds, param_names, patches) patch_optional_params(params.optionals, param_names, patches) patch_rest_param(params.rest, param_names, patches) patch_post_params(params.posts, param_names, patches) patch_keyword_params(params.keywords, param_names, patches) patch_keyword_rest(params.keyword_rest, param_names, patches) patch_block_param_node(params.block, param_names, patches) end |
#patch_for_node(node, patches, analysis, mangled_key) ⇒ void
This method returns an undefined value.
194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 194 def patch_for_node(node, patches, analysis, mangled_key) syntax_key = AstUtils.line_col_key(node) data = analysis.syntax_data[syntax_key] return unless data target_name = data[mangled_key] #: String? return unless target_name idx = node.index return unless idx.is_a?(Prism::LocalVariableTargetNode) patches << { start: idx.location.start_offset, end: idx.location.end_offset, replacement: target_name } end |
#patch_keyword_hash(node, patches, rename_map) {|arg0| ... } ⇒ void
This method returns an undefined value.
259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 259 def patch_keyword_hash(node, patches, rename_map, &block) node.elements.each do |elem| if elem.is_a?(Prism::AssocNode) result = patch_assoc(elem, patches, rename_map, keyword_arg: true) if result != :skip_children elem.compact_child_nodes.each { |child| walk_prism(child, &block) } end else walk_prism(elem, &block) end end end |
#patch_keyword_params(keywords, param_names, patches) ⇒ void
This method returns an undefined value.
138 139 140 141 142 143 144 145 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 138 def patch_keyword_params(keywords, param_names, patches) return unless keywords keywords.each do |p| short = param_names[p.name] next unless short && short != p.name.to_s patches << { start: p.name_loc.start_offset, end: p.name_loc.end_offset, replacement: "#{short}:" } end end |
#patch_keyword_rest(keyword_rest, param_names, patches) ⇒ void
This method returns an undefined value.
147 148 149 150 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 147 def patch_keyword_rest(keyword_rest, param_names, patches) return unless keyword_rest.is_a?(Prism::KeywordRestParameterNode) && keyword_rest.name patch_named_param(keyword_rest.name, keyword_rest.name_loc, param_names, patches) end |
#patch_multi_target_params(node, param_names, patches) ⇒ void
This method returns an undefined value.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 86 def patch_multi_target_params(node, param_names, patches) node.lefts.each do |p| if p.is_a?(Prism::RequiredParameterNode) short = param_names[p.name] next unless short && short != p.name.to_s patches << { start: p.location.start_offset, end: p.location.end_offset, replacement: short } elsif p.is_a?(Prism::MultiTargetNode) patch_multi_target_params(p, param_names, patches) end end if node.rest.is_a?(Prism::SplatNode) && node.rest.expression.is_a?(Prism::RequiredParameterNode) p = node.rest.expression short = param_names[p.name] if short && short != p.name.to_s patches << { start: p.location.start_offset, end: p.location.end_offset, replacement: short } end end end |
#patch_named_param(name, name_loc, param_names, patches) ⇒ void
This method returns an undefined value.
Shared tail of the rest/**rest/&block patchers: Prism types their name_loc as nullable, but a named parameter always carries one.
117 118 119 120 121 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 117 def patch_named_param(name, name_loc, param_names, patches) short = param_names[name] return unless name_loc && short && short != name.to_s patches << { start: name_loc.start_offset, end: name_loc.end_offset, replacement: short } end |
#patch_optional_params(optionals, param_names, patches) ⇒ void
This method returns an undefined value.
106 107 108 109 110 111 112 113 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 106 def patch_optional_params(optionals, param_names, patches) return unless optionals optionals.each do |p| short = param_names[p.name] next unless short && short != p.name.to_s patches << { start: p.name_loc.start_offset, end: p.name_loc.end_offset, replacement: short } end end |
#patch_post_params(posts, param_names, patches) ⇒ void
This method returns an undefined value.
128 129 130 131 132 133 134 135 136 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 128 def patch_post_params(posts, param_names, patches) return unless posts posts.each do |p| next unless p.is_a?(Prism::RequiredParameterNode) short = param_names[p.name] next unless short && short != p.name.to_s patches << { start: p.location.start_offset, end: p.location.end_offset, replacement: short } end end |
#patch_required_params(requireds, param_names, patches) ⇒ void
This method returns an undefined value.
73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 73 def patch_required_params(requireds, param_names, patches) return unless requireds requireds.each do |p| if p.is_a?(Prism::MultiTargetNode) patch_multi_target_params(p, param_names, patches) elsif p.is_a?(Prism::RequiredParameterNode) short = param_names[p.name] next unless short && short != p.name.to_s patches << { start: p.location.start_offset, end: p.location.end_offset, replacement: short } end end end |
#patch_rest_param(rest, param_names, patches) ⇒ void
This method returns an undefined value.
123 124 125 126 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 123 def patch_rest_param(rest, param_names, patches) return unless rest.is_a?(Prism::RestParameterNode) && rest.name patch_named_param(rest.name, rest.name_loc, param_names, patches) end |
#patch_variable(node, patches, rename_map) ⇒ void
This method returns an undefined value.
30 31 32 33 34 35 36 37 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 30 def patch_variable(node, patches, rename_map) key = prism_location_key(node) short = rename_map[key] return unless short loc = node.location patches << { start: loc.start_offset, end: loc.end_offset, replacement: short } end |
#patch_variable_name_only(node, patches, rename_map) ⇒ void
This method returns an undefined value.
39 40 41 42 43 44 45 46 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 39 def patch_variable_name_only(node, patches, rename_map) key = prism_location_key(node) short = rename_map[key] return unless short name_loc = node.name_loc patches << { start: name_loc.start_offset, end: name_loc.end_offset, replacement: short } end |
#prism_location_key(node) ⇒ location_key
Same key the analysis stored the rename under. Kept as its own name because the patchers only ever pass Prism nodes, but it must not grow a second implementation — the two sides sharing one definition is the point.
26 27 28 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 26 def prism_location_key(node) AstUtils.location_key(node) end |
#walk_prism(node) {|arg0| ... } ⇒ void
This method returns an undefined value.
10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/ryac/pipeline/rename_patcher.rb', line 10 def walk_prism(node, &block) return unless node result = yield node return if result == :skip_children children = node.compact_child_nodes if node.is_a?(Prism::MatchWriteNode) children = children.reject { |c| c.is_a?(Prism::LocalVariableTargetNode) } end children.each { |child| walk_prism(child, &block) } end |