class SyntaxSuggest::AroundBlockScan
此类用于探索代码块之前和之后的内容
它在传入代码块的上方和下方搜索以匹配您给定的任何条件
示例
def dog # 1 puts "bark" # 2 puts "bark" # 3 end # 4 scan = AroundBlockScan.new( code_lines: code_lines block: CodeBlock.new(lines: code_lines[1]) ) scan.scan_while { true } puts scan.before_index # => 0 puts scan.after_index # => 3
公共类方法
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 30 def initialize(code_lines:, block:) @code_lines = code_lines @orig_indent = block.current_indent @stop_after_kw = false @force_add_empty = false @force_add_hidden = false @target_indent = nil @scanner = ScanHistory.new(code_lines: code_lines, block: block) end
公共实例方法
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 217 def code_block CodeBlock.new(lines: lines) end
将当前匹配的行作为 ‘CodeBlock’ 返回
当创建 ‘CodeBlock’ 时,它会收集关于自身的元数据,因此这不是一个免费的转换。避免分配比需要的更多的 CodeBlock
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 60 def force_add_empty @force_add_empty = true self end
当使用此标志时,‘scan_while’ 将绕过给定的代码块,并始终添加一个对 ‘CodeLine#empty?’ 返回真值的行
空行不包含代码,只包含空格,例如前导空格和换行符。
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 228 def inspect "#<#{self.class}:0x0000123843lol >" end
可管理的 rspec 错误
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 223 def lines @scanner.lines end
返回当前扫描匹配的行,作为 CodeLines 的数组
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 141 def lookahead_balance_one_line kw_count = 0 end_count = 0 lines.each do |line| kw_count += 1 if line.is_kw? end_count += 1 if line.is_end? end return self if kw_count == end_count # nothing to balance @scanner.commit_if_changed # Rollback point if we don't find anything to optimize # Try to eat up empty lines @scanner.scan( up: ->(line, _, _) { line.hidden? || line.empty? }, down: ->(line, _, _) { line.hidden? || line.empty? } ) # More ends than keywords, check if we can balance expanding up next_up = @scanner.next_up next_down = @scanner.next_down case end_count - kw_count when 1 if next_up&.is_kw? && next_up.indent >= @target_indent @scanner.scan( up: ->(line, _, _) { line == next_up }, down: ->(line, _, _) { false } ) @scanner.commit_if_changed end when -1 if next_down&.is_end? && next_down.indent >= @target_indent @scanner.scan( up: ->(line, _, _) { false }, down: ->(line, _, _) { line == next_down } ) @scanner.commit_if_changed end end # Rollback any uncommitted changes @scanner.stash_changes self end
扫描是有意保守的,因为我们无法回滚一个激进的代码块(目前)
如果一个代码块因某些琐碎的原因(例如空行)而停止,但下一行会使其平衡,那么我们可以检查该条件并向上或向下获取多一行。
例如,如果我们在下面向上扫描,第 2 行可能会导致扫描停止。这是因为空行可能表示用户打算分块代码的逻辑中断,这是一个停止并检查有效性的好地方。不幸的是,这也意味着我们可能有一个“悬空”的关键字或 end。
1 def bark 2 3 end
如果第 2 行和第 3 行在代码块中,那么当运行此方法时,它会看到它是不平衡的,但是获取第 1 行会使其平衡,这就是它的作用。
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 200 def scan_adjacent_indent before_after_indent = [] before_after_indent << (@scanner.next_up&.indent || 0) before_after_indent << (@scanner.next_down&.indent || 0) @target_indent = before_after_indent.min scan_while { |line| line.not_empty? && line.indent >= @target_indent } self end
基于代码块上方/下方下一行的缩进扫描代码块
确定当前代码块上方/下方下一行的缩进。
通常,当一个代码块扩展以捕获所有相同(或更大)缩进的“邻居”并且需要扩展时,会调用此方法。例如,围绕方法的 ‘def/end` 行。
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 188 def scan_neighbors_not_empty @target_indent = @orig_indent scan_while { |line| line.not_empty? && line.indent >= @target_indent } end
查找具有相同或更大缩进的代码行,并将它们添加到代码块
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 88 def scan_while stop_next_up = false stop_next_down = false @scanner.scan( up: ->(line, kw_count, end_count) { next false if stop_next_up next true if @force_add_hidden && line.hidden? next true if @force_add_empty && line.empty? if @stop_after_kw && kw_count > end_count stop_next_up = true end yield line }, down: ->(line, kw_count, end_count) { next false if stop_next_down next true if @force_add_hidden && line.hidden? next true if @force_add_empty && line.empty? if @stop_after_kw && end_count > kw_count stop_next_down = true end yield line } ) self end
主要工作方法
scan_while
方法接受一个代码块,该代码块会产生代码块上方和下方的行。如果 yield 返回 true,则修改 @before_index 或 @after_index 以包含匹配的行。
除了产生单独的行之外,此对象的内部结构还提供了一个迷你 DSL 来处理常见情况,例如如果我们在一个方向或另一个方向找到关键字/end 不匹配则停止。
源代码
# File lib/syntax_suggest/around_block_scan.rb, line 73 def stop_after_kw @stop_after_kw = true self end
告诉 ‘scan_while’ 查找不匹配的关键字/end
向上扫描时,如果我们看到的关键字比 end 多,它将停止。当在方法体外部扫描时可能会发生这种情况。第一个向上扫描的行将是一个关键字,此设置将触发停止。
向下扫描时,如果 end 比关键字多,则停止。