[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / lib / syntax_suggest / parse_blocks_from_indent_line.rb
blob39dfca55d2dc2488d2fb4bf6587eefc575f0b08d
1 # frozen_string_literal: true
3 module SyntaxSuggest
4   # This class is responsible for generating initial code blocks
5   # that will then later be expanded.
6   #
7   # The biggest concern when guessing code blocks, is accidentally
8   # grabbing one that contains only an "end". In this example:
9   #
10   #   def dog
11   #     begonn # misspelled `begin`
12   #     puts "bark"
13   #     end
14   #   end
15   #
16   # The following lines would be matched (from bottom to top):
17   #
18   #   1) end
19   #
20   #   2) puts "bark"
21   #      end
22   #
23   #   3) begonn
24   #      puts "bark"
25   #      end
26   #
27   # At this point it has no where else to expand, and it will yield this inner
28   # code as a block
29   class ParseBlocksFromIndentLine
30     attr_reader :code_lines
32     def initialize(code_lines:)
33       @code_lines = code_lines
34     end
36     # Builds blocks from bottom up
37     def each_neighbor_block(target_line)
38       scan = AroundBlockScan.new(code_lines: code_lines, block: CodeBlock.new(lines: target_line))
39         .force_add_empty
40         .force_add_hidden
41         .scan_while { |line| line.indent >= target_line.indent }
43       neighbors = scan.code_block.lines
45       block = CodeBlock.new(lines: neighbors)
46       if neighbors.length <= 2 || block.valid?
47         yield block
48       else
49         until neighbors.empty?
50           lines = [neighbors.pop]
51           while (block = CodeBlock.new(lines: lines)) && block.invalid? && neighbors.any?
52             lines.prepend neighbors.pop
53           end
55           yield block if block
56         end
57       end
58     end
59   end
60 end