класс 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 отобразит все предоставленные строки, а не только видимые, используя метод original для их получения.
Открытые методы класса
Исходный код
# 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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.