класс Prism::ParseResult::Comments
После разбора исходного кода у нас есть дерево синтаксического анализа и список найденных комментариев. Этот класс отвечает за обход дерева и поиск ближайшего места для прикрепления каждого комментария.
Для этого он сначала находит ближайшие места к каждому комментарию. Места могут быть получены непосредственно из узлов или из полей местоположения узлов. Например, у узла класса `ClassNode` есть общее местоположение, охватывающее весь класс, но также есть местоположение для ключевого слова `class`.
После того, как ближайшие места найдены, определяется, к какому из них прикрепить комментарий. Если это заключительный комментарий (комментарий на той же строке, что и другой исходный код), он будет предпочитать прикрепление к ближайшему месту, которое предшествует комментарию. В противном случае он будет предпочитать прикрепление к ближайшему месту, которое следует за комментарием.
Атрибуты
Результат разбора, к которому мы прикрепляем комментарии.
Общедоступные методы класса
Исходный код
# File lib/prism/parse_result/comments.rb, line 86 def initialize(parse_result) @parse_result = parse_result end
Создает новый объект Comments, который будет прикреплять комментарии к заданному результату разбора.
Общедоступные методы экземпляра
Исходный код
# File lib/prism/parse_result/comments.rb, line 92
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 119
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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.