класс SyntaxSuggest::CodeLine
Представляет отдельную строку кода из данного исходного файла
Этот объект содержит метаданные о строке, такие как отступы, пустая она или нет, и лексические данные, такие как наличие ключевого слова ‘end` или других ключевых слов.
Видимость строк может быть отключена. Отметка строки как невидимой означает, что она не должна использоваться для проверки синтаксиса. Функционально это эквивалентно её комментарию.
Пример:
line = CodeLine.from_source("def foo\n").first
line.number => 1
line.empty? # => false
line.visible? # => true
line.mark_invisible
line.visible? # => false
Константы
- TRAILING_SLASH
Атрибуты
Когда строка кода помечена как невидимая, мы сохраняем её исходное значение. Это полезно для отладки и для отображения дополнительного контекста
DisplayCodeWithLineNumbers отобразит все строки, которые ему переданы, а не только видимые, используя исходный метод для их получения.
Публичные Классовые Методы
# File lib/syntax_suggest/code_line.rb, line 29
def self.from_source(source, lines: nil)
lines ||= source.lines
lex_array_for_line = LexAll.new(source: source, source_lines: lines).each_with_object(Hash.new { |h, k| h[k] = [] }) { |lex, hash| hash[lex.line] << lex }
lines.map.with_index do |line, index|
CodeLine.new(
line: line,
index: index,
lex: lex_array_for_line[index + 1]
)
end
end Возвращает массив объектов CodeLine из строки исходного кода
# File lib/syntax_suggest/code_line.rb, line 42
def initialize(line:, index:, lex:)
@lex = lex
@line = line
@index = index
@original = line
@line_number = @index + 1
strip_line = line.dup
strip_line.lstrip!
@indent = if (@empty = strip_line.empty?)
line.length - 1 # Newline removed from strip_line is not "whitespace"
else
line.length - strip_line.length
end
set_kw_end
end Публичные Методы Экземпляров
# File lib/syntax_suggest/code_line.rb, line 150 def <=>(other) index <=> other.index end
Оператор сравнения, необходимый для проверки равенства и сортировки
# File lib/syntax_suggest/code_line.rb, line 115 def empty? @empty end
Строка «пустая» — это строка, которая была изначально пустой в исходном коде, в то время как «скрытая» строка — это строка, которую мы позже пометили как «невидимую»
Противное или «видимое?» (отличается от `empty?`)
# File lib/syntax_suggest/code_line.rb, line 172 def ignore_newline_not_beg? @ignore_newline_not_beg end
- Нестабильный API
-
Строки, имеющие маркер типа «on_ignored_nl», но НЕ типа «BEG», кажутся хорошим приближением для возможности объединения нескольких строк в одну.
Этот предикат используется для определения, когда выполнены эти два условия.
Известный случай, который не обрабатывается:
Ripper.lex <<~EOM a && b || c EOM
По какой-то причине это приводит к появлению «on_ignore_newline», но с типом BEG
# File lib/syntax_suggest/code_line.rb, line 72 def indent_index @indent_index ||= [indent, index] end
Используется для устойчивой сортировки по уровню отступа
Сортировка в Ruby не является «устойчивой», что означает, что когда несколько элементов имеют одинаковое значение, они не гарантированно возвращаются в том же порядке, в котором были помещены.
Поэтому, когда несколько строк кода имеют одинаковый уровень отступа, они сортируются по значению их индекса, которое уникально и постоянно.
Это в основном необходимо для согласованности набора тестов
# File lib/syntax_suggest/code_line.rb, line 87 def is_end? @is_end end
Возвращает true, если строка кода содержит ключевое слово ‘end`
# File lib/syntax_suggest/code_line.rb, line 81 def is_kw? @is_kw end
Возвращает true, если строка кода содержит ключевое слово, которое совпадает с ‘end`
Например: ‘def`, `do`, `begin`, `ensure` и т.д.
# File lib/syntax_suggest/code_line.rb, line 96 def mark_invisible @line = "" end
Используется для скрытия строк
Алгоритм поиска сгруппирует строки в блоки, а затем, если эти блоки определены как представляющие действительный код, они будут скрыты
# File lib/syntax_suggest/code_line.rb, line 120 def not_empty? !empty? end
Противное к ‘empty?` (отличается от `visible?`)
# File lib/syntax_suggest/code_line.rb, line 133 def to_s line end
Отображает заданную строку
Также позволяет представить исходный код как массив строк кода.
При вызове метода ‘join` на массиве элементов он вызовет `to_s` на каждом элементе, что по сути конвертирует его обратно в исходную строку.
# File lib/syntax_suggest/code_line.rb, line 184 def trailing_slash? last = @lex.last last&.type == :on_tstring_end end
# File lib/syntax_suggest/code_line.rb, line 103 def visible? !line.empty? end
Означает, что строка была помечена как «невидимая». Непонятно, «пустые» строки видимы... они просто не содержат исходного кода, кроме новой строки («n»).
Приватные Методы Экземпляров
# File lib/syntax_suggest/code_line.rb, line 206
def set_kw_end
oneliner_count = 0
in_oneliner_def = nil
kw_count = 0
end_count = 0
@ignore_newline_not_beg = false
@lex.each do |lex|
kw_count += 1 if lex.is_kw?
end_count += 1 if lex.is_end?
if lex.type == :on_ignored_nl
@ignore_newline_not_beg = !lex.expr_beg?
end
if in_oneliner_def.nil?
in_oneliner_def = :ENDFN if lex.state.allbits?(Ripper::EXPR_ENDFN)
elsif lex.state.allbits?(Ripper::EXPR_ENDFN)
# Continue
elsif lex.state.allbits?(Ripper::EXPR_BEG)
in_oneliner_def = :BODY if lex.token == "="
elsif lex.state.allbits?(Ripper::EXPR_END)
# We found an endless method, count it
oneliner_count += 1 if in_oneliner_def == :BODY
in_oneliner_def = nil
else
in_oneliner_def = nil
end
end
kw_count -= oneliner_count
@is_kw = (kw_count - end_count) > 0
@is_end = (end_count - kw_count) > 0
end Обнаружение методов без конца
Из github.com/ruby/irb/commit/826ae909c9c93a2ddca6f9cfcd9c94dbf53d44ab Обнаружение «строки на одной строке» похоже требует автомата со стеком. Это можно сделать, в основном, смотря на «состояние» (последнее значение):
ENDFN -> BEG (token = '=' ) -> END
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.