class SyntaxSuggest::BlockExpand
此类负责获取一个位于较远缩进处的代码块,然后迭代地增加该代码块,使其捕获同一缩进块内的所有内容。
def dog puts "bow" puts "wow" end
block = BlockExpand.new
(code_lines: code_lines)
.call(CodeBlock.new(lines: code_lines[1]))
puts block.to_s # => puts “bow”
puts "wow"
一旦代码块捕获了给定缩进级别的所有内容,它将扩展以捕获周围的缩进。
block = BlockExpand.new
(code_lines: code_lines)
.call(block)
block.to_s # => def dog
puts "bow" puts "wow" end
公共类方法
# File syntax_suggest/block_expand.rb, line 34 def initialize(code_lines:) @code_lines = code_lines end
公共实例方法
主要接口。扩展当前缩进,然后再扩展到较低的缩进
# File syntax_suggest/block_expand.rb, line 40 def call(block) if (next_block = expand_neighbors(block)) next_block else expand_indent(block) end end
将代码扩展到下一个最低缩进
例如
1 def dog 2 print "dog" 3 end
如果一个代码块从第 2 行开始,那么它已经捕获了它所有的“邻居”(相同或更高缩进处的代码)。要继续扩展,这个代码块必须捕获位于不同缩进级别的第一行和第三行。
此方法允许完全扩展的代码块降低其缩进级别(以便它们可以扩展以捕获更多上下代码)。它会保守地执行此操作,因为没有撤消操作(目前)。
# File syntax_suggest/block_expand.rb, line 63 def expand_indent(block) now = AroundBlockScan.new(code_lines: @code_lines, block: block) .force_add_hidden .stop_after_kw .scan_adjacent_indent now.lookahead_balance_one_line now.code_block end
邻居是位于当前缩进线或以上的代码。
首先,我们构建一个包含所有邻居的代码块。如果我们无法进一步扩展,那么我们会降低缩进阈值并通过缩进扩展,即 `expand_indent`。
处理两种一般情况。
## 情况 1:检查方法/类/等等内部的代码
需要注意的是,即使给定缩进级别中的所有内容是有效代码的一部分,也并非所有内容都可以解析为有效的代码。例如
1 hash = { 2 name: "richard", 3 dog: "cinco", 4 }
在这种情况下,第 2 行和第 3 行将是邻居,但在对其调用 `expand_indent` 之前,它们是无效的。
当我们在方法或类(在相同的缩进级别)中添加代码时,使用空行来表示程序员预期的逻辑块。停止并检查每一个。例如
1 def dog 2 print "dog" 3 4 hash = { 5 end
如果我们不在空换行符处停止解析,那么代码块可能会错误地捕获所有内容(第 2、3 和 4 行),并将其报告为存在问题,而不是仅报告第 4 行。
## 情况 2:扩展/获取其他逻辑块
一旦搜索算法将给定缩进处的所有行转换为代码块,它将接着执行 `expand_indent`。一旦生成的代码块作为邻居扩展,我们开始看到邻居是其他的逻辑块,即代码块的邻居可能是另一个方法或类(带有关键字/结束符)。
例如
1 def bark 2 3 end 4 5 def sit 6 end
在这种情况下,如果第 4、5 和 6 行在一个代码块中,当它尝试扩展邻居时,它将向上扩展。如果它在第 2 或 3 行后停止,可能会导致问题,因为存在有效的 kw/end 对,但是将在不包含它的情况下检查代码块。
我们尝试通过下面的 `lookahead_balance_one_line` 来解决这种边缘情况。
# File syntax_suggest/block_expand.rb, line 130 def expand_neighbors(block) now = AroundBlockScan.new(code_lines: @code_lines, block: block) # Initial scan now .force_add_hidden .stop_after_kw .scan_neighbors_not_empty # Slurp up empties now .scan_while { |line| line.empty? } # If next line is kw and it will balance us, take it expanded_lines = now .lookahead_balance_one_line .lines # Don't allocate a block if it won't be used # # If nothing was taken, return nil to indicate that status # used in `def call` to determine if # we need to expand up/out (`expand_indent`) if block.lines == expanded_lines nil else CodeBlock.new(lines: expanded_lines) end end
可管理的 rspec 错误
# File syntax_suggest/block_expand.rb, line 161 def inspect "#<SyntaxSuggest::CodeBlock:0x0000123843lol >" end