類別 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 行後停止,可能會造成問題,因為有一個有效的關鍵字/結尾配對,但區塊會在沒有它的情況下被檢查。

我們嘗試使用以下「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