class 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
负责在给定的封装节点上下文中,找到给定注释最接近的目标。