класс 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"]
Атрибуты
Публичные Классовые Методы
Исходный код
# 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 Публичные Методы Экземпляров
Исходный код
# 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 Основной цикл поиска
Исходный код
# 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 Парсит строки с наибольшим отступом в блоки, которые помечаются и добавляются в фронт
Исходный код
# 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
Расширяет существующий блок в фронте, чтобы увидеть, содержит ли он недействительный синтаксис
Исходный код
# 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
Исходный код
# 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 Используется для отладки
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.