類別 SyntaxSuggest::CodeSearch
搜尋程式碼中的語法錯誤
演算法有三個主要階段
-
清除/格式化輸入來源
-
搜尋無效區塊
-
將無效區塊格式化成有意義的內容
此類別處理的部分。
大部分繁重的工作在
- CodeFrontier (Holds information for generating blocks and determining if we can stop searching) - ParseBlocksFromLine (Creates blocks into the frontier) - BlockExpand (Expands existing blocks to search more code)
## 語法錯誤偵測
當邊界包含語法錯誤時,我們可以停止搜尋
search = CodeSearch.new(<<~EOM) def dog def lol end EOM search.call search.invalid_blocks.map(&:to_s) # => # => ["def lol\n"]
屬性
code_lines[R]
frontier[R]
invalid_blocks[R]
record_dir[R]
公開類別方法
new(source, record_dir: DEFAULT_VALUE) 按一下以切換來源
# File lib/syntax_suggest/code_search.rb, line 44 def initialize(source, record_dir: DEFAULT_VALUE) record_dir = if record_dir == DEFAULT_VALUE (ENV["SYNTAX_SUGGEST_RECORD_DIR"] || ENV["SYNTAX_SUGGEST_DEBUG"]) ? "tmp" : nil else record_dir end if record_dir @record_dir = SyntaxSuggest.record_dir(record_dir) @write_count = 0 end @tick = 0 @source = source @name_tick = Hash.new { |hash, k| hash[k] = 0 } @invalid_blocks = [] @code_lines = CleanDocument.new(source: source).call.lines @frontier = CodeFrontier.new(code_lines: @code_lines) @block_expand = BlockExpand.new(code_lines: @code_lines) @parse_blocks_from_indent_line = ParseBlocksFromIndentLine.new(code_lines: @code_lines) end
公開實例方法
call() 按一下以切換來源
主要搜尋迴圈
# File lib/syntax_suggest/code_search.rb, line 123 def call until frontier.holds_all_syntax_errors? @tick += 1 if frontier.expand? expand_existing else create_blocks_from_untracked_lines end end @invalid_blocks.concat(frontier.detect_invalid_blocks) @invalid_blocks.sort_by! { |block| block.starts_at } self end
create_blocks_from_untracked_lines() 按一下以切換來源
將縮排最深的行解析成區塊,標記並新增到邊界
# File lib/syntax_suggest/code_search.rb, line 100 def create_blocks_from_untracked_lines max_indent = frontier.next_indent_line&.indent while (line = frontier.next_indent_line) && (line.indent == max_indent) @parse_blocks_from_indent_line.each_neighbor_block(frontier.next_indent_line) do |block| push(block, name: "add") end end end
expand_existing() 按一下以切換來源
給定邊界中已存在的區塊,擴充它以查看它是否包含我們的無效語法
# File lib/syntax_suggest/code_search.rb, line 112 def expand_existing block = frontier.pop return unless block record(block: block, name: "before-expand") block = @block_expand.call(block) push(block, name: "expand") end
push(block, name:) 按一下以切換來源
# File lib/syntax_suggest/code_search.rb, line 91 def push(block, name:) record(block: block, name: name) block.mark_invisible if block.valid? frontier << block end
record(block:, name: "record") 按一下以切換來源
用於除錯
# File lib/syntax_suggest/code_search.rb, line 69 def record(block:, name: "record") return unless @record_dir @name_tick[name] += 1 filename = "#{@write_count += 1}-#{name}-#{@name_tick[name]}-(#{block.starts_at}__#{block.ends_at}).txt" if ENV["SYNTAX_SUGGEST_DEBUG"] puts "\n\n==== #{filename} ====" puts "\n```#{block.starts_at}..#{block.ends_at}" puts block puts "```" puts " block indent: #{block.current_indent}" end @record_dir.join(filename).open(mode: "a") do |f| document = DisplayCodeWithLineNumbers.new( lines: @code_lines.select(&:visible?), terminal: false, highlight_lines: block.lines ).call f.write(" Block lines: #{block.starts_at..block.ends_at} (#{name}) \n\n#{document}") end end