
- Since moving `comments_hash` to `Stanza`, we've been using the wrong kind of "comments": the comments for the _stanza_, not the comments for the entire Cask. - Add a test to ensure this actually works. There was previously an infinite loop here due to the bad `comments`, visible in a `StanzaOrder` cop test, which I speculatively added a failing test for. Turns out that supporting nested stanza _ordering_ (vs. just grouping) is a whole separate piece of work (there are multiple TODOs there already), so I've backed that out and will do that separately.
75 lines
2.0 KiB
Ruby
75 lines
2.0 KiB
Ruby
# typed: true
|
|
# frozen_string_literal: true
|
|
|
|
require "forwardable"
|
|
|
|
module RuboCop
|
|
module Cask
|
|
module AST
|
|
# This class wraps the AST block node that represents the entire cask
|
|
# definition. It includes various helper methods to aid cops in their
|
|
# analysis.
|
|
class CaskBlock
|
|
extend Forwardable
|
|
|
|
def initialize(block_node, comments)
|
|
@block_node = block_node
|
|
@comments = comments
|
|
end
|
|
|
|
attr_reader :block_node, :comments
|
|
|
|
alias cask_node block_node
|
|
|
|
def_delegator :cask_node, :block_body, :cask_body
|
|
|
|
def header
|
|
@header ||= CaskHeader.new(cask_node.method_node)
|
|
end
|
|
|
|
def stanzas
|
|
return [] unless cask_body
|
|
|
|
@stanzas ||= cask_body.each_node
|
|
.select(&:stanza?)
|
|
.map { |node| Stanza.new(node, comments) }
|
|
end
|
|
|
|
def toplevel_stanzas
|
|
# If a `cask` block only contains one stanza, it is that stanza's direct parent,
|
|
# otherwise stanzas are grouped in a block and `cask` is that block's parent.
|
|
is_toplevel_stanza = if cask_body.begin_block?
|
|
->(stanza) { stanza.parent_node.parent.cask_block? }
|
|
else
|
|
->(stanza) { stanza.parent_node.cask_block? }
|
|
end
|
|
|
|
@toplevel_stanzas ||= stanzas.select(&is_toplevel_stanza)
|
|
end
|
|
|
|
def sorted_toplevel_stanzas
|
|
@sorted_toplevel_stanzas ||= sort_stanzas(toplevel_stanzas)
|
|
end
|
|
|
|
private
|
|
|
|
def sort_stanzas(stanzas)
|
|
stanzas.sort do |s1, s2|
|
|
i1 = stanza_order_index(s1)
|
|
i2 = stanza_order_index(s2)
|
|
if i1 == i2 || i1.blank? || i2.blank?
|
|
i1 = stanzas.index(s1)
|
|
i2 = stanzas.index(s2)
|
|
end
|
|
i1 - i2
|
|
end
|
|
end
|
|
|
|
def stanza_order_index(stanza)
|
|
Constants::STANZA_ORDER.index(stanza.stanza_name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|