Class: Synvert::Core::Rewriter::Instance
- Inherits:
-
Object
- Object
- Synvert::Core::Rewriter::Instance
- Includes:
- Helper
- Defined in:
- lib/synvert/core/rewriter/instance.rb
Overview
Instance is an execution unit, it finds specified ast nodes, checks if the nodes match some conditions, then add, replace or remove code.
One instance can contains one or many [Synvert::Core::Rewriter::Scope] and [Synvert::Rewriter::Condition].
Instance Attribute Summary collapse
-
#current_file ⇒ Object
Current filename.
-
#current_node ⇒ Object
Current parsing node.
Class Method Summary collapse
-
.file_ast(file_path) ⇒ String
Cached file ast.
-
.file_source(file_path) ⇒ String
Cached file source.
-
.reset ⇒ Object
Reset cached file source and ast.
-
.write_file(file_path, source) ⇒ Object
Write source to file and remove cached file source and ast.
Instance Method Summary collapse
-
#any_value ⇒ Object
Any value but nil.
-
#append(code) ⇒ Object
Parse append dsl, it creates a [Synvert::Core::Rewriter::AppendAction] to append the code to the bottom of current node body.
-
#delete(*selectors) ⇒ Object
Parse delete dsl, it creates a [Synvert::Core::Rewriter::DeleteAction] to delete child nodes.
-
#file_source ⇒ Object
Current file source.
-
#goto_node(child_node_name, &block) ⇒ Object
Parse goto_node dsl, it creates a [Synvert::Core::Rewriter::GotoScope] to go to a child node, then continue operating on the child node.
-
#if_exist_node(rules, &block) ⇒ Object
Parse if_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfExistCondition] to check if matching nodes exist in the child nodes, if so, then continue operating on each matching ast node.
-
#if_only_exist_node(rules, &block) ⇒ Object
Parse if_only_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfOnlyExistCondition] to check if current node has only one child node and the child node matches rules, if so, then continue operating on each matching ast node.
-
#initialize(rewriter, file_patterns, &block) ⇒ Synvert::Core::Rewriter::Instance
constructor
Initialize an instance.
-
#insert(code, at: 'end') ⇒ Object
Parse insert dsl, it creates a [Synvert::Core::Rewriter::InsertAction] to insert the code to the top of current node body.
-
#insert_after(node) ⇒ Object
Parse insert_after dsl, it creates a [Synvert::Core::Rewriter::InsertAfterAction] to insert the code next to the current node.
-
#node ⇒ Parser::AST::Node
Gets current node, it allows to get current node in block code.
-
#prepend(code) ⇒ Object
Parse prepend dsl, it creates a [Synvert::Core::Rewriter::PrependAction] to prepend the code to the top of current node body.
-
#process ⇒ Object
Process the instance.
-
#process_with_node(node) { ... } ⇒ Object
Set current_node to node and process.
-
#process_with_other_node(node) { ... } ⇒ Object
Set current_node properly, process and set current_node back to original current_node.
-
#remove ⇒ Object
Parse remove dsl, it creates a [Synvert::Core::Rewriter::RemoveAction] to remove current node.
-
#replace(*selectors, with:) ⇒ Object
Parse replace with dsl, it creates a [Synvert::Core::Rewriter::ReplaceAction] to replace child nodes with code.
-
#replace_erb_stmt_with_expr ⇒ Object
Parse replace_erb_stmt_with_expr dsl, it creates a [Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction] to replace erb stmt code to expr code.
-
#replace_with(code) ⇒ Object
Parse replace_with dsl, it creates a [Synvert::Core::Rewriter::ReplaceWithAction] to replace current node with code.
-
#unless_exist_node(rules, &block) ⇒ Object
Parse unless_exist_node dsl, it creates a [Synvert::Core::Rewriter::UnlessExistCondition] to check if matching nodes doesn’t exist in the child nodes, if so, then continue operating on each matching ast node.
-
#warn(message) ⇒ Object
Parse warn dsl, it creates a [Synvert::Core::Rewriter::Warning] to save warning message.
-
#within_direct_node(rules, &block) ⇒ Object
(also: #with_direct_node)
Parse within_direct_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find direct matching ast nodes, then continue operating on each matching ast node.
-
#within_node(rules, options = nil, &block) ⇒ Object
(also: #with_node)
Parse within_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find recursive matching ast nodes, then continue operating on each matching ast node.
-
#wrap(with:, indent: nil) ⇒ Object
Parse wrap with dsl, it creates a [Synvert::Core::Rewriter::WrapAction] to wrap current node with code.
Methods included from Helper
#add_arguments_with_parenthesis_if_necessary, #add_curly_brackets_if_necessary, #add_receiver_if_necessary, #reject_keys_from_hash, #strip_brackets
Constructor Details
#initialize(rewriter, file_patterns, &block) ⇒ Synvert::Core::Rewriter::Instance
Initialize an instance.
78 79 80 81 82 83 84 |
# File 'lib/synvert/core/rewriter/instance.rb', line 78 def initialize(rewriter, file_patterns, &block) @rewriter = rewriter @actions = [] @file_patterns = file_patterns @block = block rewriter.helpers.each { |helper| singleton_class.send(:define_method, helper[:name], &helper[:block]) } end |
Instance Attribute Details
#current_file ⇒ Object
Returns current filename.
65 |
# File 'lib/synvert/core/rewriter/instance.rb', line 65 attr_accessor :current_node, :current_file |
#current_node ⇒ Object
Returns current parsing node.
65 66 67 |
# File 'lib/synvert/core/rewriter/instance.rb', line 65 def current_node @current_node end |
Class Method Details
.file_ast(file_path) ⇒ String
Cached file ast.
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/synvert/core/rewriter/instance.rb', line 30 def file_ast(file_path) @file_ast ||= {} @file_ast[file_path] ||= begin buffer = Parser::Source::Buffer.new file_path buffer.source = file_source(file_path) parser = Parser::CurrentRuby.new parser.reset parser.parse buffer end end |
.file_source(file_path) ⇒ String
Cached file source.
16 17 18 19 20 21 22 23 24 |
# File 'lib/synvert/core/rewriter/instance.rb', line 16 def file_source(file_path) @file_source ||= {} @file_source[file_path] ||= begin source = File.read(file_path, encoding: 'UTF-8') source = Engine::ERB.encode(source) if /\.erb$/.match?(file_path) source end end |
.reset ⇒ Object
Reset cached file source and ast.
55 56 57 58 |
# File 'lib/synvert/core/rewriter/instance.rb', line 55 def reset @file_source = {} @file_ast = {} end |
.write_file(file_path, source) ⇒ Object
Write source to file and remove cached file source and ast.
47 48 49 50 51 52 |
# File 'lib/synvert/core/rewriter/instance.rb', line 47 def write_file(file_path, source) source = Engine::ERB.decode(source) if /\.erb/.match?(file_path) File.write(file_path, source.gsub(/ +\n/, "\n")) @file_source[file_path] = nil @file_ast[file_path] = nil end |
Instance Method Details
#any_value ⇒ Object
Any value but nil.
307 308 309 |
# File 'lib/synvert/core/rewriter/instance.rb', line 307 def any_value Rewriter::AnyValue.new end |
#append(code) ⇒ Object
Parse append dsl, it creates a [Synvert::Core::Rewriter::AppendAction] to append the code to the bottom of current node body.
226 227 228 |
# File 'lib/synvert/core/rewriter/instance.rb', line 226 def append(code) @actions << Rewriter::AppendAction.new(self, code).process end |
#delete(*selectors) ⇒ Object
Parse delete dsl, it creates a [Synvert::Core::Rewriter::DeleteAction] to delete child nodes.
286 287 288 |
# File 'lib/synvert/core/rewriter/instance.rb', line 286 def delete(*selectors) @actions << Rewriter::DeleteAction.new(self, *selectors).process end |
#file_source ⇒ Object
Current file source
68 69 70 |
# File 'lib/synvert/core/rewriter/instance.rb', line 68 def file_source self.class.file_source(current_file) end |
#goto_node(child_node_name, &block) ⇒ Object
Parse goto_node dsl, it creates a [Synvert::Core::Rewriter::GotoScope] to go to a child node, then continue operating on the child node.
190 191 192 |
# File 'lib/synvert/core/rewriter/instance.rb', line 190 def goto_node(child_node_name, &block) Rewriter::GotoScope.new(self, child_node_name, &block).process end |
#if_exist_node(rules, &block) ⇒ Object
Parse if_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfExistCondition] to check if matching nodes exist in the child nodes, if so, then continue operating on each matching ast node.
199 200 201 |
# File 'lib/synvert/core/rewriter/instance.rb', line 199 def if_exist_node(rules, &block) Rewriter::IfExistCondition.new(self, rules, &block).process end |
#if_only_exist_node(rules, &block) ⇒ Object
Parse if_only_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfOnlyExistCondition] to check if current node has only one child node and the child node matches rules, if so, then continue operating on each matching ast node.
218 219 220 |
# File 'lib/synvert/core/rewriter/instance.rb', line 218 def if_only_exist_node(rules, &block) Rewriter::IfOnlyExistCondition.new(self, rules, &block).process end |
#insert(code, at: 'end') ⇒ Object
Parse insert dsl, it creates a [Synvert::Core::Rewriter::InsertAction] to insert the code to the top of current node body.
243 244 245 |
# File 'lib/synvert/core/rewriter/instance.rb', line 243 def insert(code, at: 'end') @actions << Rewriter::InsertAction.new(self, code, at: at).process end |
#insert_after(node) ⇒ Object
Parse insert_after dsl, it creates a [Synvert::Core::Rewriter::InsertAfterAction] to insert the code next to the current node.
251 252 253 |
# File 'lib/synvert/core/rewriter/instance.rb', line 251 def insert_after(node) @actions << Rewriter::InsertAfterAction.new(self, node).process end |
#node ⇒ Parser::AST::Node
Gets current node, it allows to get current node in block code.
132 133 134 |
# File 'lib/synvert/core/rewriter/instance.rb', line 132 def node @current_node end |
#prepend(code) ⇒ Object
Parse prepend dsl, it creates a [Synvert::Core::Rewriter::PrependAction] to prepend the code to the top of current node body.
234 235 236 |
# File 'lib/synvert/core/rewriter/instance.rb', line 234 def prepend(code) @actions << Rewriter::PrependAction.new(self, code).process end |
#process ⇒ Object
Process the instance. It finds all files, for each file, it executes the block code, gets all rewrite actions, and rewrite source code back to original file.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/synvert/core/rewriter/instance.rb', line 89 def process @file_patterns.each do |file_pattern| Dir.glob(File.join(Configuration.path, file_pattern)).each do |file_path| next if Configuration.skip_files.include? file_path begin puts file_path if Configuration.show_run_process conflict_actions = [] source = +self.class.file_source(file_path) ast = self.class.file_ast(file_path) @current_file = file_path process_with_node ast do begin instance_eval(&@block) rescue NoMethodError puts @current_node.debug_info raise end end if @actions.length > 0 @actions.sort_by! { |action| [action.begin_pos, action.end_pos] } conflict_actions = get_conflict_actions @actions.reverse_each do |action| source[action.begin_pos...action.end_pos] = action.rewritten_code end @actions = [] update_file(file_path, source) end rescue Parser::SyntaxError puts "[Warn] file #{file_path} was not parsed correctly." # do nothing, iterate next file end while !conflict_actions.empty? end end end |
#process_with_node(node) { ... } ⇒ Object
Set current_node to node and process.
140 141 142 143 144 |
# File 'lib/synvert/core/rewriter/instance.rb', line 140 def process_with_node(node) self.current_node = node yield self.current_node = node end |
#process_with_other_node(node) { ... } ⇒ Object
Set current_node properly, process and set current_node back to original current_node.
150 151 152 153 154 155 |
# File 'lib/synvert/core/rewriter/instance.rb', line 150 def process_with_other_node(node) original_node = current_node self.current_node = node yield self.current_node = original_node end |
#remove ⇒ Object
Parse remove dsl, it creates a [Synvert::Core::Rewriter::RemoveAction] to remove current node.
279 280 281 |
# File 'lib/synvert/core/rewriter/instance.rb', line 279 def remove @actions << Rewriter::RemoveAction.new(self).process end |
#replace(*selectors, with:) ⇒ Object
Parse replace with dsl, it creates a [Synvert::Core::Rewriter::ReplaceAction] to replace child nodes with code.
268 269 270 |
# File 'lib/synvert/core/rewriter/instance.rb', line 268 def replace(*selectors, with:) @actions << Rewriter::ReplaceAction.new(self, *selectors, with: with).process end |
#replace_erb_stmt_with_expr ⇒ Object
Parse replace_erb_stmt_with_expr dsl, it creates a [Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction] to replace erb stmt code to expr code.
274 275 276 |
# File 'lib/synvert/core/rewriter/instance.rb', line 274 def replace_erb_stmt_with_expr @actions << Rewriter::ReplaceErbStmtWithExprAction.new(self).process end |
#replace_with(code) ⇒ Object
Parse replace_with dsl, it creates a [Synvert::Core::Rewriter::ReplaceWithAction] to replace current node with code.
259 260 261 |
# File 'lib/synvert/core/rewriter/instance.rb', line 259 def replace_with(code) @actions << Rewriter::ReplaceWithAction.new(self, code).process end |
#unless_exist_node(rules, &block) ⇒ Object
Parse unless_exist_node dsl, it creates a [Synvert::Core::Rewriter::UnlessExistCondition] to check if matching nodes doesn’t exist in the child nodes, if so, then continue operating on each matching ast node.
208 209 210 |
# File 'lib/synvert/core/rewriter/instance.rb', line 208 def unless_exist_node(rules, &block) Rewriter::UnlessExistCondition.new(self, rules, &block).process end |
#warn(message) ⇒ Object
Parse warn dsl, it creates a [Synvert::Core::Rewriter::Warning] to save warning message.
302 303 304 |
# File 'lib/synvert/core/rewriter/instance.rb', line 302 def warn() @rewriter.add_warning Rewriter::Warning.new(self, ) end |
#within_direct_node(rules, &block) ⇒ Object Also known as: with_direct_node
Parse within_direct_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find direct matching ast nodes, then continue operating on each matching ast node.
179 180 181 |
# File 'lib/synvert/core/rewriter/instance.rb', line 179 def within_direct_node(rules, &block) Rewriter::WithinScope.new(self, rules, { direct: true }, &block).process end |
#within_node(rules, options = nil, &block) ⇒ Object Also known as: with_node
Parse within_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find recursive matching ast nodes, then continue operating on each matching ast node.
167 168 169 170 |
# File 'lib/synvert/core/rewriter/instance.rb', line 167 def within_node(rules, = nil, &block) ||= { stop_when_match: false } Rewriter::WithinScope.new(self, rules, , &block).process end |
#wrap(with:, indent: nil) ⇒ Object
Parse wrap with dsl, it creates a [Synvert::Core::Rewriter::WrapAction] to wrap current node with code.
295 296 297 |
# File 'lib/synvert/core/rewriter/instance.rb', line 295 def wrap(with:, indent: nil) @actions << Rewriter::WrapAction.new(self, with: with, indent: indent).process end |