class Prism::Node
Этот класс представляет узел дерева. Он является родительским классом для всех различных типов узлов.
Атрибуты
Битовый набор флагов для этого узла. Некоторые флаги являются общими для всех узлов, а некоторые узлы имеют собственные флаги.
Уникальный идентификатор этого узла. Он используется в особом случае, когда нужно сохранить ссылку на узел, не удерживая в памяти всё синтаксическое дерево. Этот уникальный идентификатор будет одинаковым при многократном разборе одного и того же исходного кода.
Указатель на исходный текст, из которого был создан этот узел.
Публичные методы класса
# File lib/prism/node.rb, line 245
def self.fields
# This method should only be called on subclasses of Node, not Node
# itself.
raise NoMethodError, "undefined method `fields' for #{inspect}" if self == Node
Reflection.fields_for(self)
end Возвращает список полей, существующих для этого класса узлов. Поля описывают структуру узла. Такая рефлексия полезна, например, для рекурсивного обхода каждого узла и поля дерева.
Публичные методы экземпляра
# File lib/prism/node.rb, line 231
def breadth_first_search(&block)
queue = [self] #: Array[Prism::node]
while (node = queue.shift)
return node if yield node
queue.concat(node.compact_child_nodes)
end
nil
end Возвращает первый узел, соответствующий переданному блоку при обходе в глубину. Это удобно для поиска узла, удовлетворяющего определённому условию.
node.breadth_first_search { |node| node.node_id == node_id }
# File lib/prism/node.rb, line 118 def cached_end_code_units_column(cache) location.cached_end_code_units_column(cache) end
Передаёт вызов методу cached_end_code_units_column связанного объекта расположения.
# File lib/prism/node.rb, line 86 def cached_end_code_units_offset(cache) location.cached_end_code_units_offset(cache) end
Передаёт вызов методу cached_end_code_units_offset связанного объекта расположения.
# File lib/prism/node.rb, line 112 def cached_start_code_units_column(cache) location.cached_start_code_units_column(cache) end
Передаёт вызов методу cached_start_code_units_column связанного объекта расположения.
# File lib/prism/node.rb, line 80 def cached_start_code_units_offset(cache) location.cached_start_code_units_offset(cache) end
Передаёт вызов методу cached_start_code_units_offset связанного объекта расположения.
# File lib/prism/node.rb, line 133 def comments location.comments end
Передаёт вызов методу получения комментариев связанного объекта расположения.
# File lib/prism/node.rb, line 106 def end_character_column location.end_character_column end
Передаёт вызов методу end_character_column связанного объекта расположения.
# File lib/prism/node.rb, line 74 def end_character_offset location.end_character_offset end
Передаёт вызов методу end_character_offset связанного объекта расположения.
# File lib/prism/node.rb, line 96 def end_column location.end_column end
Передаёт вызов методу end_column связанного объекта расположения.
# File lib/prism/node.rb, line 50 def end_line location.end_line end
Передаёт вызов методу end_line связанного объекта расположения.
# File lib/prism/node.rb, line 63 def end_offset location = @location location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF)) end
Конечное смещение узла в исходном тексте. По сути, этот метод делегирует вызов объекту расположения.
# File lib/prism/node.rb, line 123 def leading_comments location.leading_comments end
Передаёт вызов методу leading_comments связанного объекта расположения.
# File lib/prism/node.rb, line 33 def location location = @location return location if location.is_a?(Location) @location = Location.new(source, location >> 32, location & 0xFFFFFFFF) end
Экземпляр Location, представляющий расположение этого узла в исходном тексте.
# File lib/prism/node.rb, line 164 def newline? flags.anybits?(NodeFlags::NEWLINE) end
Возвращает true, если для узла установлен флаг перевода строки.
# File lib/prism/node.rb, line 175
def pretty_print(q)
q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line|
q.text(line.chomp)
end
q.current_group.break
end Подобен inspect, но учитывает текущий уровень отступа, заданный объектом форматированного вывода.
# File lib/prism/node.rb, line 27 def save(repository) repository.enter(node_id, :itself) end
Сохраняет этот узел с помощью сохранённого исходного текста, чтобы его можно было получить позже.
# File lib/prism/node.rb, line 40 def save_location(repository) repository.enter(node_id, :location) end
Сохраняет расположение с помощью сохранённого исходного текста, чтобы его можно было получить позже.
Псевдоним для source_lines, используемый для имитации API RubyVM::AbstractSyntaxTree, чтобы упростить миграцию.
# File lib/prism/node.rb, line 147 def slice location.slice end
Извлекает из исходного текста фрагмент, соответствующий расположению узла.
# File lib/prism/node.rb, line 154 def slice_lines location.slice_lines end
Извлекает из исходного текста фрагмент, соответствующий расположению узла: от начала строки, в которой начинается расположение, до конца строки, в которой оно заканчивается.
# File lib/prism/node.rb, line 138 def source_lines location.source_lines end
Возвращает все строки исходного кода, связанные с этим узлом.
# File lib/prism/node.rb, line 101 def start_character_column location.start_character_column end
Передаёт вызов методу start_character_column связанного объекта расположения.
# File lib/prism/node.rb, line 69 def start_character_offset location.start_character_offset end
Передаёт вызов методу start_character_offset связанного объекта расположения.
# File lib/prism/node.rb, line 91 def start_column location.start_column end
Передаёт вызов методу start_column связанного объекта расположения.
# File lib/prism/node.rb, line 45 def start_line location.start_line end
Передаёт вызов методу start_line связанного объекта расположения.
# File lib/prism/node.rb, line 56 def start_offset location = @location location.is_a?(Location) ? location.start_offset : location >> 32 end
Начальное смещение узла в исходном тексте. По сути, этот метод делегирует вызов объекту расположения.
# File lib/prism/node.rb, line 169 def static_literal? flags.anybits?(NodeFlags::STATIC_LITERAL) end
Возвращает true, если для узла установлен флаг статического литерала.
# File lib/prism/node.rb, line 183
def to_dot
# @type self: node
DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot
end Преобразует этот узел в строку графа Graphviz DOT.
# File lib/prism/node.rb, line 128 def trailing_comments location.trailing_comments end
Передаёт вызов методу trailing_comments связанного объекта расположения.
# File lib/prism/node.rb, line 194
def tunnel(line, column)
queue = [self] #: Array[Prism::node]
result = [] #: Array[Prism::node]
while (node = queue.shift)
result << node
node.compact_child_nodes.each do |child_node|
child_location = child_node.location
start_line = child_location.start_line
end_line = child_location.end_line
if start_line == end_line
if line == start_line && column >= child_location.start_column && column < child_location.end_column
queue << child_node
break
end
elsif (line == start_line && column >= child_location.start_column) || (line == end_line && column < child_location.end_column)
queue << child_node
break
elsif line > start_line && line < end_line
queue << child_node
break
end
end
end
result
end Возвращает список узлов — потомков этого узла, содержащих указанную строку и столбец. Это удобно для поиска узла, выбранного по строке и столбцу исходного кода.
Важно отметить, что столбец, передаваемый этому методу, должен быть задан в байтах, а не в символах или кодовых единицах.
Интерфейс Node
↑ наверхПубличные методы класса
# File lib/prism/node.rb, line 310
def self.type
raise NoMethodError, "undefined method `type' for #{inspect}"
end Подобно type, этот метод возвращает символ, позволяющий выбирать действия по типу узла без длинной цепочки ===. Обратите внимание: как и type, он всё же работает медленнее, чем == для одного класса, но должен быть быстрее в операторе case или при сравнении с массивом.
Публичные методы экземпляра
# File lib/prism/node.rb, line 261
def accept(visitor)
raise NoMethodError, "undefined method `accept' for #{inspect}"
end Принимает посетителя и вызывает соответствующую специализированную функцию посещения.
# File lib/prism/node.rb, line 267
def child_nodes
raise NoMethodError, "undefined method `child_nodes' for #{inspect}"
end Возвращает массив дочерних узлов, включая nil на месте отсутствующих необязательных узлов.
# File lib/prism/node.rb, line 281
def comment_targets
raise NoMethodError, "undefined method `comment_targets' for #{inspect}"
end Возвращает массив дочерних узлов и расположений, к которым потенциально могут быть привязаны комментарии.
# File lib/prism/node.rb, line 275
def compact_child_nodes
raise NoMethodError, "undefined method `compact_child_nodes' for #{inspect}"
end Возвращает массив дочерних узлов, исключая все nil на месте отсутствующих необязательных узлов.
# File lib/prism/node.rb, line 286
def inspect
raise NoMethodError, "undefined method `inspect' for #{inspect}"
end Возвращает строковое представление узла.
# File lib/prism/node.rb, line 302
def type
raise NoMethodError, "undefined method `type' for #{inspect}"
end Иногда требуется проверить экземпляр узла по списку классов, чтобы определить, какое поведение выполнить. Обычно для этого вызывают [cls1, cls2].include?(node.class) или помещают узел в оператор case и используют case node; when cls1; when cls2; end. Оба подхода относительно медленны из-за поиска констант, вызовов методов и/или выделения памяти под массивы.
Вместо этого можно вызвать type, который вернёт символ для сравнения. Этот способ быстрее остальных, поскольку использует одно сравнение целых чисел. Кроме того, при использовании CRuby можно воспользоваться тем, что операторы case, содержащие только символьные ключи, используют таблицу переходов.
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.