Module: Synvert::Core::Engine::Elegant
Overview
Engine::Elegant provides some helper methods for engines
who read block code without end.
For those engines, it will try to insert end\n
when encode,
while delete end\n
when generate_transform_proc.
Constant Summary collapse
- END_LINE =
"end\n"
- WHITESPACE =
' '
- DO_BLOCK_REGEX =
/ do(\s|\z|\n)/
- IF_KEYWORDS =
%w[if unless begin case for while until]
- ELSE_KEYWORDS =
%w[else elsif when in rescue ensure]
Instance Method Summary collapse
-
#generate_transform_proc(encoded_source) ⇒ Proc
Generate transform proc, it's used to adjust start and end position of actions.
-
#insert_end?(leading_spaces_counts, current_leading_spaces_count, equal = true) ⇒ Boolean
Check if the current leading_spaces_count is less than or equal to the last leading_spaces_count in leading_spaces_counts.
- #scan_ruby_expression(scanner, new_code, leading_spaces_counts, leading_spaces_count) ⇒ Object
- #scan_ruby_interpolation_and_plain_text(scanner, new_code, leading_spaces_counts, leading_spaces_count) ⇒ Object
- #scan_ruby_statement(scanner, new_code, leading_spaces_counts, leading_spaces_count) ⇒ Object
Instance Method Details
#generate_transform_proc(encoded_source) ⇒ Proc
Generate transform proc, it's used to adjust start and end position of actions.
Due to the fact that we insert end\n
when encode the source code, we need to adjust
start and end position of actions to match the original source code.
e.g. if end\n exists in position 10, action start position is 20 and end position is 30,
then action start position should be 16 and end position should be 26.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/synvert/core/engine/elegant.rb', line 25 def generate_transform_proc(encoded_source) proc do |actions| start = 0 indices = [] loop do index = encoded_source[start..-1].index(END_LINE) break unless index indices << (start + index) start += index + END_LINE.length end indices.each do |index| NodeMutation::Helper.iterate_actions(actions) do |action| action.start -= END_LINE.length if action.start > index action.end -= END_LINE.length if action.end > index end end end end |
#insert_end?(leading_spaces_counts, current_leading_spaces_count, equal = true) ⇒ Boolean
Check if the current leading_spaces_count is less than or equal to the last leading_spaces_count in leading_spaces_counts. If so, pop the last leading_spaces_count and return true.
47 48 49 50 51 52 53 54 55 |
# File 'lib/synvert/core/engine/elegant.rb', line 47 def insert_end?(leading_spaces_counts, current_leading_spaces_count, equal = true) operation = equal ? :<= : :< if !leading_spaces_counts.empty? && current_leading_spaces_count.send(operation, leading_spaces_counts.last) leading_spaces_counts.pop true else false end end |
#scan_ruby_expression(scanner, new_code, leading_spaces_counts, leading_spaces_count) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/synvert/core/engine/elegant.rb', line 79 def scan_ruby_expression(scanner, new_code, leading_spaces_counts, leading_spaces_count) if insert_end?(leading_spaces_counts, leading_spaces_count) new_code << END_LINE end rest = scanner.scan(/.*?(\z|\n)/) if rest =~ DO_BLOCK_REGEX leading_spaces_counts << leading_spaces_count end new_code << rest while rest.rstrip.end_with?(',') rest = scanner.scan(/.*?(\z|\n)/) if rest =~ DO_BLOCK_REGEX leading_spaces_counts << leading_spaces_count end new_code << rest end end |
#scan_ruby_interpolation_and_plain_text(scanner, new_code, leading_spaces_counts, leading_spaces_count) ⇒ Object
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 128 |
# File 'lib/synvert/core/engine/elegant.rb', line 98 def scan_ruby_interpolation_and_plain_text(scanner, new_code, leading_spaces_counts, leading_spaces_count) if insert_end?(leading_spaces_counts, leading_spaces_count) new_code << END_LINE end while scanner.scan(/(.*?)(\\*)#\{/) # it matches interpolation " #{current_user.login}" new_code << (WHITESPACE * scanner.matched.size) unless scanner.matched[-3] == '\\' count = 1 while scanner.scan(/.*?([\{\}])/) if scanner.matched[-1] == '}' count -= 1 if count == 0 new_code << (scanner.matched[0..-2] + ';') break else new_code << scanner.matched end else count += 1 new_code << scanner.matched end end end end if scanner.scan(/.*?\z/) new_code << (WHITESPACE * scanner.matched.size) end if scanner.scan(/.*?\n/) new_code << ((WHITESPACE * (scanner.matched.size - 1)) + "\n") end end |
#scan_ruby_statement(scanner, new_code, leading_spaces_counts, leading_spaces_count) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/synvert/core/engine/elegant.rb', line 57 def scan_ruby_statement(scanner, new_code, leading_spaces_counts, leading_spaces_count) new_code << scanner.scan(/\s*/) keyword = scanner.scan(/\w+/) rest = scanner.scan(/.*?(\z|\n)/) if insert_end?(leading_spaces_counts, leading_spaces_count, !ELSE_KEYWORDS.include?(keyword)) new_code << END_LINE end if IF_KEYWORDS.include?(keyword) || rest =~ DO_BLOCK_REGEX leading_spaces_counts << leading_spaces_count end new_code << keyword new_code << rest while rest.rstrip.end_with?(',') rest = scanner.scan(/.*?(\z|\n)/) if IF_KEYWORDS.include?(keyword) || rest =~ DO_BLOCK_REGEX leading_spaces_counts << leading_spaces_count end new_code << rest end end |