类 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

公共类方法

new(code_lines:) 点击切换源代码
# File lib/syntax_suggest/block_expand.rb, line 34
def initialize(code_lines:)
  @code_lines = code_lines
end

公共实例方法

call(block) 点击切换源代码

主要接口。扩展当前缩进,然后扩展到更低的缩进级别。

# File lib/syntax_suggest/block_expand.rb, line 40
def call(block)
  if (next_block = expand_neighbors(block))
    next_block
  else
    expand_indent(block)
  end
end
expand_indent(block) 点击切换源代码

将代码扩展到下一个较低的缩进级别。

例如

1 def dog
2   print "dog"
3 end

如果一个块从第 2 行开始,那么它已经捕获了所有“邻居”(相同或更高缩进级别的代码)。为了继续扩展,这个块必须捕获第 1 行和第 3 行,它们位于不同的缩进级别。

此方法允许完全扩展的块降低其缩进级别(以便它们可以扩展以捕获更多向上和向下的代码)。它以保守的方式执行此操作,因为目前没有撤消功能。

# File lib/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_neighbors(block) 点击切换源代码

邻居是指位于当前缩进行或其上方的代码。

首先,我们构建一个包含所有邻居的块。如果我们无法进一步扩展,那么我们将降低缩进阈值并通过缩进进行扩展,即“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:扩展/获取其他逻辑块

一旦搜索算法将所有行转换为给定缩进级别的块,它将“扩展缩进”。一旦生成的块作为邻居扩展,我们就会开始看到邻居是其他逻辑块,即一个块的邻居可能是另一个方法或类(带有关键字/结尾的东西)。

例如

1 def bark
2
3 end
4
5 def sit
6 end

在这种情况下,如果第 4、5 和 6 行在一个块中,当它尝试扩展邻居时,它将向上扩展。如果它在第 2 或 3 行之后停止,可能会导致问题,因为存在有效的 kw/end 对,但该块将在没有它的情况下进行检查。

我们尝试使用下面的“lookahead_balance_one_line”来解决这个边缘情况。

# File lib/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
inspect() 点击以切换源代码

可管理的 rspec 错误

# File lib/syntax_suggest/block_expand.rb, line 161
def inspect
  "#<SyntaxSuggest::CodeBlock:0x0000123843lol >"
end