класс Prism::ParseResult::Comments
После разбора исходного кода у нас есть и синтаксическое дерево, и список комментариев, найденных в исходном коде. Этот класс отвечает за обход дерева и поиск ближайшего места для прикрепления каждого комментария.
Сначала он находит ближайшие места для каждого комментария. Эти места могут быть получены непосредственно из узлов или из полей расположения узлов. Например, ClassNode имеет общее расположение, охватывающее весь класс, но также имеет расположение для ключевого слова class.
Найдя ближайшие места, класс определяет, к какому из них прикрепить комментарий. Если это завершающий комментарий (комментарий в той же строке, что и другой исходный код), предпочтение отдается ближайшему месту перед комментарием. В противном случае предпочтение отдается ближайшему месту после комментария.
Атрибуты
Результат разбора, к которому прикрепляются комментарии.
Публичные методы класса
# File lib/prism/parse_result/comments.rb, line 87 def initialize(parse_result) @parse_result = parse_result end
Создает новый объект Comments, который прикрепляет комментарии к указанному результату разбора.
Публичные методы экземпляра
# File lib/prism/parse_result/comments.rb, line 93
def attach!
parse_result.comments.each do |comment|
preceding, enclosing, following = nearest_targets(parse_result.value, comment)
if comment.trailing?
if preceding
preceding.trailing_comment(comment)
else
(following || enclosing || NodeTarget.new(parse_result.value)).leading_comment(comment)
end
else
# If a comment exists on its own line, prefer a leading comment.
if following
following.leading_comment(comment)
elsif preceding
preceding.trailing_comment(comment)
else
(enclosing || NodeTarget.new(parse_result.value)).leading_comment(comment)
end
end
end
end Прикрепляет комментарии к соответствующим местам в дереве, изменяя результат разбора.
Приватные методы экземпляра
# File lib/prism/parse_result/comments.rb, line 120
def nearest_targets(node, comment)
comment_start = comment.location.start_offset
comment_end = comment.location.end_offset
targets = [] #: Array[_Target]
node.comment_targets.map do |value|
case value
when StatementsNode
targets.concat(value.body.map { |node| NodeTarget.new(node) })
when Node
targets << NodeTarget.new(value)
when Location
targets << LocationTarget.new(value)
end
end
targets.sort_by!(&:start_offset)
preceding = nil #: _Target?
following = nil #: _Target?
left = 0
right = targets.length
# This is a custom binary search that finds the nearest nodes to the
# given comment. When it finds a node that completely encapsulates the
# comment, it recurses downward into the tree.
while left < right
middle = (left + right) / 2
target = targets[middle]
target_start = target.start_offset
target_end = target.end_offset
if target.encloses?(comment)
# @type var target: NodeTarget
# The comment is completely contained by this target. Abandon the
# binary search at this level.
return nearest_targets(target.node, comment)
end
if target_end <= comment_start
# This target falls completely before the comment. Because we will
# never consider this target or any targets before it again, this
# target must be the closest preceding target we have encountered so
# far.
preceding = target
left = middle + 1
next
end
if comment_end <= target_start
# This target falls completely after the comment. Because we will
# never consider this target or any targets after it again, this
# target must be the closest following target we have encountered so
# far.
following = target
right = middle
next
end
# This should only happen if there is a bug in this parser.
raise "Comment location overlaps with a target location"
end
[preceding, NodeTarget.new(node), following]
end Отвечает за поиск ближайших целей для указанного комментария в контексте указанного охватывающего узла.
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.