Module: Astel::Rewriter::Structured
- Included in:
- Astel::Rewriter
- Defined in:
- lib/astel/rewriter/structured.rb,
lib/astel/rewriter/structured/comments.rb,
lib/astel/rewriter/structured/formatting.rb,
lib/astel/rewriter/structured/collections.rb,
lib/astel/rewriter/structured/source_indenter.rb
Instance Method Summary collapse
- #comment_out(node) ⇒ Object
- #dedent(text) ⇒ Object
- #find_keyword_argument(call_node, name) ⇒ Object
- #indent(text, level: 1) ⇒ Object
- #indentation_of(node) ⇒ Object
- #insert_into_body(node, source_text, position: :end) ⇒ Object
- #insert_keyword_argument(call_node, text, position: :last) ⇒ Object
- #insert_line_after(node, text) ⇒ Object
- #insert_line_before(node, text) ⇒ Object
- #insert_list_element(collection_node, index, text) ⇒ Object
- #leading_comments(node) ⇒ Object
- #reindent(text, to:) ⇒ Object
- #remove_keyword_argument(call_node, name) ⇒ Object
- #remove_line(node) ⇒ Object
- #remove_list_element(collection_node, element_node) ⇒ Object
- #remove_list_elements(collection_node, element_nodes) ⇒ Object
- #remove_with_comments(node) ⇒ Object
- #replace_keyword_key(assoc_node, name) ⇒ Object
- #replace_keyword_value(assoc_node, replacement) ⇒ Object
- #trailing_comment(node) ⇒ Object
Instance Method Details
#comment_out(node) ⇒ Object
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 56 def comment_out(node) first = @source_file.line_start(node.location.start_offset) last = @source_file.line_end([node_end_offset(node) - 1, node.location.start_offset].max) text = @source_file.source.byteslice(first, last - first) commented = text.lines(chomp: false).map do |line| indentation = line[/\A[ \t]*/] "#{indentation}# #{line.delete_prefix(indentation)}" end.join replace(first...last, commented) end |
#dedent(text) ⇒ Object
17 18 19 20 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 17 def dedent(text) width = dedentation_width(text) text.lines(chomp: false).map { |line| line.strip.empty? ? line : line.byteslice(width..) }.join end |
#find_keyword_argument(call_node, name) ⇒ Object
8 9 10 11 12 13 14 |
# File 'lib/astel/rewriter/structured.rb', line 8 def find_keyword_argument(call_node, name) keyword_hashes(call_node).each do |keyword_hash| match = keyword_hash.elements.find { |element| keyword_name(element) == name.to_sym } return match if match end nil end |
#indent(text, level: 1) ⇒ Object
12 13 14 15 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 12 def indent(text, level: 1) prefix = @source_file.indent_unit * level text.lines(chomp: false).map { |line| line.strip.empty? ? line : "#{prefix}#{line}" }.join end |
#indentation_of(node) ⇒ Object
8 9 10 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 8 def indentation_of(node) @source_file.indentation_at(node.location.start_offset) end |
#insert_into_body(node, source_text, position: :end) ⇒ Object
27 28 29 30 31 32 33 34 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 27 def insert_into_body(node, source_text, position: :end) statements = body_statements(node) target, after, section_break = body_insertion_target(node, statements, position) content = format_body_source(source_text, body_child_indentation(node, statements)) return insert_body_source_after(node, target, content) if after insert_body_source_before(node, target, content, section_break: section_break) end |
#insert_keyword_argument(call_node, text, position: :last) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/astel/rewriter/structured.rb', line 43 def insert_keyword_argument(call_node, text, position: :last) raise ArgumentError, 'position must be :first or :last' unless i[first last].include?(position) arguments = call_node.arguments return insert_first_keyword_argument(call_node, text) unless arguments keyword_hash = keyword_hashes(call_node).first return insert_into_keyword_hash(keyword_hash, text, position) if keyword_hash index = arguments.arguments.length insert_list_element(arguments, index, text) end |
#insert_line_after(node, text) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 49 def insert_line_after(node, text) line = @source_file.line_location_with_newline(node_end_offset(node) - 1) content = format_body_source(text, indentation_of(node)) prefix = line_terminated?(line) ? '' : @source_file.newline insert_after(line, "#{prefix}#{content}#{@source_file.newline}") end |
#insert_line_before(node, text) ⇒ Object
43 44 45 46 47 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 43 def insert_line_before(node, text) line_start = @source_file.line_start(node.location.start_offset) content = format_body_source(text, indentation_of(node)) insert_before(line_start...line_start, "#{content}#{@source_file.newline}") end |
#insert_list_element(collection_node, index, text) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/astel/rewriter/structured/collections.rb', line 30 def insert_list_element(collection_node, index, text) elements = collection_elements(collection_node) raise IndexError, 'list index is outside the collection' unless index.between?(0, elements.length) if elements.empty? opening = collection_node.respond_to?(:opening_loc) && collection_node.opening_loc raise ArgumentError, 'cannot locate an empty collection body' unless opening return insert_into_empty_delimited(collection_node, text) end if index < elements.length target = elements[index] return insert_before(target.location, "#{text}#{list_separator(collection_node, target)}") end last = elements.last insert_after(last.location, "#{list_separator(collection_node, last)}#{text}") end |
#leading_comments(node) ⇒ Object
6 7 8 9 |
# File 'lib/astel/rewriter/structured/comments.rb', line 6 def leading_comments(node) attach_comments node.location.leading_comments end |
#reindent(text, to:) ⇒ Object
22 23 24 25 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 22 def reindent(text, to:) prefix = indentation_of(to) dedent(text).lines(chomp: false).map { |line| line.strip.empty? ? line : "#{prefix}#{line}" }.join end |
#remove_keyword_argument(call_node, name) ⇒ Object
16 17 18 19 20 21 22 23 24 |
# File 'lib/astel/rewriter/structured.rb', line 16 def remove_keyword_argument(call_node, name) argument = find_keyword_argument(call_node, name) return self unless argument keyword_hash = keyword_hashes(call_node).find { |hash| hash.elements.include?(argument) } return remove_sole_keyword_argument(call_node, keyword_hash) if keyword_hash.elements.one? remove_list_element(keyword_hash, argument) end |
#remove_line(node) ⇒ Object
36 37 38 39 40 41 |
# File 'lib/astel/rewriter/structured/formatting.rb', line 36 def remove_line(node) remove_lines_if_isolated( start_offset: node.location.start_offset, end_offset: node_end_offset(node) ) end |
#remove_list_element(collection_node, element_node) ⇒ Object
6 7 8 |
# File 'lib/astel/rewriter/structured/collections.rb', line 6 def remove_list_element(collection_node, element_node) remove_list_elements(collection_node, [element_node]) end |
#remove_list_elements(collection_node, element_nodes) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/astel/rewriter/structured/collections.rb', line 10 def remove_list_elements(collection_node, element_nodes) elements = collection_elements(collection_node) indexes = element_indexes(elements, element_nodes) return self if indexes.empty? trailing_end = trailing_comma_end(elements.last) start_offset = elements.first.location.start_offset content = content_without_elements( elements, indexes, start_offset: start_offset, end_offset: trailing_end ) extra_ranges = indexes.flat_map { |index| heredoc_ranges(elements[index]) } return replace(start_offset...trailing_end, content) if extra_ranges.empty? transaction(raise_on_conflict: true) do |rewriter| rewriter.replace(start_offset...trailing_end, content) extra_ranges.each { |range| rewriter.remove(range) } end self end |
#remove_with_comments(node) ⇒ Object
16 17 18 19 20 21 22 |
# File 'lib/astel/rewriter/structured/comments.rb', line 16 def remove_with_comments(node) comments = leading_comments(node) trailing = trailing_comment(node) start_offset = comments.empty? ? node.location.start_offset : comments.first.location.start_offset end_offset = [node_end_offset(node), trailing&.location&.end_offset].compact.max remove_lines_if_isolated(start_offset: start_offset, end_offset: end_offset) end |
#replace_keyword_key(assoc_node, name) ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/astel/rewriter/structured.rb', line 26 def replace_keyword_key(assoc_node, name) if implicit_keyword_value?(assoc_node) return replace(assoc_node.location, "#{name}: #{assoc_node.value.value.name}") end replacement = assoc_node.operator_loc ? ":#{name}" : "#{name}:" replace(assoc_node.key.location, replacement) end |
#replace_keyword_value(assoc_node, replacement) ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/astel/rewriter/structured.rb', line 35 def replace_keyword_value(assoc_node, replacement) if implicit_keyword_value?(assoc_node) return replace(assoc_node.location, "#{@source_file.slice(assoc_node.key.location)} #{replacement}") end replace_expression(assoc_node.value, replacement) end |
#trailing_comment(node) ⇒ Object
11 12 13 14 |
# File 'lib/astel/rewriter/structured/comments.rb', line 11 def trailing_comment(node) attach_comments node.location.trailing_comments.first end |