Merge pull request #15223 from issyl0/rubocop-cask-stanza-order-in-on-blocks
rubocops/cask: Check for correct stanza order within `on_*` blocks
This commit is contained in:
commit
c0f8068573
@ -6,27 +6,57 @@ require "forwardable"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cask
|
module Cask
|
||||||
module AST
|
module AST
|
||||||
# This class wraps the AST block node that represents the entire cask
|
class StanzaBlock
|
||||||
# definition. It includes various helper methods to aid cops in their
|
extend T::Helpers
|
||||||
# analysis.
|
|
||||||
class CaskBlock
|
|
||||||
extend Forwardable
|
|
||||||
|
|
||||||
|
sig { returns(RuboCop::AST::BlockNode) }
|
||||||
|
attr_reader :block_node
|
||||||
|
|
||||||
|
sig { returns(T::Array[Parser::Source::Comment]) }
|
||||||
|
attr_reader :comments
|
||||||
|
|
||||||
|
sig { params(block_node: RuboCop::AST::BlockNode, comments: T::Array[Parser::Source::Comment]).void }
|
||||||
def initialize(block_node, comments)
|
def initialize(block_node, comments)
|
||||||
@block_node = block_node
|
@block_node = block_node
|
||||||
@comments = comments
|
@comments = comments
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :block_node, :comments
|
sig { returns(T::Array[Stanza]) }
|
||||||
|
def stanzas
|
||||||
|
return [] unless (block_body = block_node.block_body)
|
||||||
|
|
||||||
alias cask_node block_node
|
# If a block only contains one stanza, it is that stanza's direct parent, otherwise
|
||||||
|
# stanzas are grouped in a nested block and the block is that nested block's parent.
|
||||||
|
is_stanza = if block_body.begin_block?
|
||||||
|
->(node) { node.parent.parent == block_node }
|
||||||
|
else
|
||||||
|
->(node) { node.parent == block_node }
|
||||||
|
end
|
||||||
|
|
||||||
|
@stanzas ||= block_body.each_node
|
||||||
|
.select(&:stanza?)
|
||||||
|
.select(&is_stanza)
|
||||||
|
.map { |node| Stanza.new(node, comments) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# 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 < StanzaBlock
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
def cask_node
|
||||||
|
block_node
|
||||||
|
end
|
||||||
|
|
||||||
def_delegator :cask_node, :block_body, :cask_body
|
def_delegator :cask_node, :block_body, :cask_body
|
||||||
|
|
||||||
def header
|
def header
|
||||||
@header ||= CaskHeader.new(cask_node.method_node)
|
@header ||= CaskHeader.new(block_node.method_node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: Use `StanzaBlock#stanzas` for all cops, where possible.
|
||||||
def stanzas
|
def stanzas
|
||||||
return [] unless cask_body
|
return [] unless cask_body
|
||||||
|
|
||||||
@ -46,28 +76,6 @@ module RuboCop
|
|||||||
|
|
||||||
@toplevel_stanzas ||= stanzas.select(&is_toplevel_stanza)
|
@toplevel_stanzas ||= stanzas.select(&is_toplevel_stanza)
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
@ -23,6 +23,7 @@ module RuboCop
|
|||||||
|
|
||||||
def_delegator :stanza_node, :parent, :parent_node
|
def_delegator :stanza_node, :parent, :parent_node
|
||||||
def_delegator :stanza_node, :arch_variable?
|
def_delegator :stanza_node, :arch_variable?
|
||||||
|
def_delegator :stanza_node, :on_system_block?
|
||||||
|
|
||||||
def source_range
|
def source_range
|
||||||
stanza_node.location_expression
|
stanza_node.location_expression
|
||||||
@ -48,6 +49,10 @@ module RuboCop
|
|||||||
Constants::STANZA_GROUP_HASH[stanza_name]
|
Constants::STANZA_GROUP_HASH[stanza_name]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stanza_index
|
||||||
|
Constants::STANZA_ORDER.index(stanza_name)
|
||||||
|
end
|
||||||
|
|
||||||
def same_group?(other)
|
def same_group?(other)
|
||||||
stanza_group == other.stanza_group
|
stanza_group == other.stanza_group
|
||||||
end
|
end
|
||||||
@ -65,7 +70,6 @@ module RuboCop
|
|||||||
def ==(other)
|
def ==(other)
|
||||||
self.class == other.class && stanza_node == other.stanza_node
|
self.class == other.class && stanza_node == other.stanza_node
|
||||||
end
|
end
|
||||||
|
|
||||||
alias eql? ==
|
alias eql? ==
|
||||||
|
|
||||||
Constants::STANZA_ORDER.each do |stanza_name|
|
Constants::STANZA_ORDER.each do |stanza_name|
|
||||||
|
|||||||
@ -14,11 +14,18 @@ module RuboCop
|
|||||||
def_node_matcher :key_node, "{(pair $_ _) (hash (pair $_ _) ...)}"
|
def_node_matcher :key_node, "{(pair $_ _) (hash (pair $_ _) ...)}"
|
||||||
def_node_matcher :val_node, "{(pair _ $_) (hash (pair _ $_) ...)}"
|
def_node_matcher :val_node, "{(pair _ $_) (hash (pair _ $_) ...)}"
|
||||||
|
|
||||||
def_node_matcher :cask_block?, "(block (send nil? :cask _) args ...)"
|
def_node_matcher :cask_block?, "(block (send nil? :cask ...) args ...)"
|
||||||
|
def_node_matcher :on_system_block?,
|
||||||
|
"(block (send nil? {#{ON_SYSTEM_METHODS.map(&:inspect).join(" ")}} ...) args ...)"
|
||||||
def_node_matcher :arch_variable?, "(lvasgn _ (send nil? :on_arch_conditional ...))"
|
def_node_matcher :arch_variable?, "(lvasgn _ (send nil? :on_arch_conditional ...))"
|
||||||
|
|
||||||
def_node_matcher :begin_block?, "(begin ...)"
|
def_node_matcher :begin_block?, "(begin ...)"
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def cask_on_system_block?
|
||||||
|
(on_system_block? && each_ancestor.any?(&:cask_block?)) || false
|
||||||
|
end
|
||||||
|
|
||||||
def stanza?
|
def stanza?
|
||||||
return true if arch_variable?
|
return true if arch_variable?
|
||||||
|
|
||||||
|
|||||||
@ -6,22 +6,46 @@ module RuboCop
|
|||||||
module Cask
|
module Cask
|
||||||
# Common functionality for cops checking casks.
|
# Common functionality for cops checking casks.
|
||||||
module CaskHelp
|
module CaskHelp
|
||||||
extend T::Helpers
|
prepend CommentsHelp
|
||||||
|
|
||||||
abstract!
|
sig { overridable.params(cask_block: RuboCop::Cask::AST::CaskBlock).void }
|
||||||
|
|
||||||
sig { abstract.params(cask_block: RuboCop::Cask::AST::CaskBlock).void }
|
|
||||||
def on_cask(cask_block); end
|
def on_cask(cask_block); end
|
||||||
|
|
||||||
|
sig { overridable.params(cask_stanza_block: RuboCop::Cask::AST::StanzaBlock).void }
|
||||||
|
def on_cask_stanza_block(cask_stanza_block); end
|
||||||
|
|
||||||
|
# FIXME: Workaround until https://github.com/rubocop/rubocop/pull/11858 is released.
|
||||||
|
def find_end_line(node)
|
||||||
|
return node.loc.end.line if node.block_type? || node.numblock_type?
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { params(block_node: RuboCop::AST::BlockNode).void }
|
||||||
def on_block(block_node)
|
def on_block(block_node)
|
||||||
super if defined? super
|
super if defined? super
|
||||||
return unless respond_to?(:on_cask)
|
|
||||||
|
return if !block_node.cask_block? && !block_node.cask_on_system_block?
|
||||||
|
|
||||||
|
comments = comments_in_range(block_node).to_a
|
||||||
|
stanza_block = RuboCop::Cask::AST::StanzaBlock.new(block_node, comments)
|
||||||
|
on_cask_stanza_block(stanza_block)
|
||||||
|
|
||||||
return unless block_node.cask_block?
|
return unless block_node.cask_block?
|
||||||
|
|
||||||
comments = processed_source.comments
|
|
||||||
cask_block = RuboCop::Cask::AST::CaskBlock.new(block_node, comments)
|
cask_block = RuboCop::Cask::AST::CaskBlock.new(block_node, comments)
|
||||||
on_cask(cask_block)
|
on_cask(cask_block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def on_system_methods(cask_stanzas)
|
||||||
|
cask_stanzas.select(&:on_system_block?)
|
||||||
|
end
|
||||||
|
|
||||||
|
def inner_stanzas(block_node, comments)
|
||||||
|
block_contents = block_node.child_nodes.select(&:begin_type?)
|
||||||
|
inner_nodes = block_contents.map(&:child_nodes).flatten.select(&:send_type?)
|
||||||
|
inner_nodes.map { |n| RuboCop::Cask::AST::Stanza.new(n, comments) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -7,7 +7,6 @@ module RuboCop
|
|||||||
class NoOverrides < Base
|
class NoOverrides < Base
|
||||||
include CaskHelp
|
include CaskHelp
|
||||||
|
|
||||||
ON_SYSTEM_METHODS = RuboCop::Cask::Constants::ON_SYSTEM_METHODS
|
|
||||||
# These stanzas can be overridden by `on_*` blocks, so take them into account.
|
# These stanzas can be overridden by `on_*` blocks, so take them into account.
|
||||||
# TODO: Update this list if new stanzas are added to `Cask::DSL` that call `set_unique_stanza`.
|
# TODO: Update this list if new stanzas are added to `Cask::DSL` that call `set_unique_stanza`.
|
||||||
OVERRIDEABLE_METHODS = [
|
OVERRIDEABLE_METHODS = [
|
||||||
@ -22,8 +21,7 @@ module RuboCop
|
|||||||
def on_cask(cask_block)
|
def on_cask(cask_block)
|
||||||
cask_stanzas = cask_block.toplevel_stanzas
|
cask_stanzas = cask_block.toplevel_stanzas
|
||||||
|
|
||||||
# Skip if there are no `on_*` blocks.
|
return if (on_blocks = on_system_methods(cask_stanzas)).none?
|
||||||
return if (on_blocks = cask_stanzas.select { |s| ON_SYSTEM_METHODS.include?(s.stanza_name) }).none?
|
|
||||||
|
|
||||||
stanzas_in_blocks = on_system_stanzas(on_blocks)
|
stanzas_in_blocks = on_system_stanzas(on_blocks)
|
||||||
|
|
||||||
@ -40,9 +38,7 @@ module RuboCop
|
|||||||
def on_system_stanzas(on_system)
|
def on_system_stanzas(on_system)
|
||||||
names = Set.new
|
names = Set.new
|
||||||
method_nodes = on_system.map(&:method_node)
|
method_nodes = on_system.map(&:method_node)
|
||||||
method_nodes.each do |node|
|
method_nodes.select(&:block_type?).each do |node|
|
||||||
next unless node.block_type?
|
|
||||||
|
|
||||||
node.child_nodes.each do |child|
|
node.child_nodes.each do |child|
|
||||||
child.each_node(:send) do |send_node|
|
child.each_node(:send) do |send_node|
|
||||||
# Skip (nested) livecheck blocks as its `url` is different to a download `url`.
|
# Skip (nested) livecheck blocks as its `url` is different to a download `url`.
|
||||||
@ -51,7 +47,7 @@ module RuboCop
|
|||||||
if send_node.ancestors.drop_while { |a| !a.begin_type? }.any? { |a| a.dstr_type? || a.regexp_type? }
|
if send_node.ancestors.drop_while { |a| !a.begin_type? }.any? { |a| a.dstr_type? || a.regexp_type? }
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
next if ON_SYSTEM_METHODS.include?(send_node.method_name)
|
next if RuboCop::Cask::Constants::ON_SYSTEM_METHODS.include?(send_node.method_name)
|
||||||
|
|
||||||
names.add(send_node.method_name)
|
names.add(send_node.method_name)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6,7 +6,7 @@ require "forwardable"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Cask
|
module Cask
|
||||||
# This cop checks that a cask's stanzas are grouped correctly.
|
# This cop checks that a cask's stanzas are grouped correctly, including nested within `on_*` blocks.
|
||||||
# @see https://docs.brew.sh/Cask-Cookbook#stanza-order
|
# @see https://docs.brew.sh/Cask-Cookbook#stanza-order
|
||||||
class StanzaGrouping < Base
|
class StanzaGrouping < Base
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
@ -14,7 +14,6 @@ module RuboCop
|
|||||||
include CaskHelp
|
include CaskHelp
|
||||||
include RangeHelp
|
include RangeHelp
|
||||||
|
|
||||||
ON_SYSTEM_METHODS = RuboCop::Cask::Constants::ON_SYSTEM_METHODS
|
|
||||||
MISSING_LINE_MSG = "stanza groups should be separated by a single empty line"
|
MISSING_LINE_MSG = "stanza groups should be separated by a single empty line"
|
||||||
EXTRA_LINE_MSG = "stanzas within the same group should have no lines between them"
|
EXTRA_LINE_MSG = "stanzas within the same group should have no lines between them"
|
||||||
|
|
||||||
@ -24,17 +23,11 @@ module RuboCop
|
|||||||
cask_stanzas = cask_block.toplevel_stanzas
|
cask_stanzas = cask_block.toplevel_stanzas
|
||||||
add_offenses(cask_stanzas)
|
add_offenses(cask_stanzas)
|
||||||
|
|
||||||
# If present, check grouping of stanzas within `on_*` blocks.
|
return if (on_blocks = on_system_methods(cask_stanzas)).none?
|
||||||
return if (on_blocks = cask_stanzas.select { |s| ON_SYSTEM_METHODS.include?(s.stanza_name) }).none?
|
|
||||||
|
|
||||||
on_blocks.map(&:method_node).each do |on_block|
|
on_blocks.map(&:method_node).select(&:block_type?).each do |on_block|
|
||||||
next unless on_block.block_type?
|
stanzas = inner_stanzas(on_block, processed_source.comments)
|
||||||
|
add_offenses(stanzas)
|
||||||
block_contents = on_block.child_nodes.select(&:begin_type?)
|
|
||||||
inner_nodes = block_contents.map(&:child_nodes).flatten.select(&:send_type?)
|
|
||||||
inner_stanzas = inner_nodes.map { |node| RuboCop::Cask::AST::Stanza.new(node, processed_source.comments) }
|
|
||||||
|
|
||||||
add_offenses(inner_stanzas)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -6,46 +6,68 @@ require "forwardable"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Cask
|
module Cask
|
||||||
# This cop checks that a cask's stanzas are ordered correctly.
|
# This cop checks that a cask's stanzas are ordered correctly, including nested within `on_*` blocks.
|
||||||
# @see https://docs.brew.sh/Cask-Cookbook#stanza-order
|
# @see https://docs.brew.sh/Cask-Cookbook#stanza-order
|
||||||
class StanzaOrder < Base
|
class StanzaOrder < Base
|
||||||
|
include IgnoredNode
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
include CaskHelp
|
include CaskHelp
|
||||||
|
|
||||||
MESSAGE = "`%<stanza>s` stanza out of order"
|
MESSAGE = "`%<stanza>s` stanza out of order"
|
||||||
|
|
||||||
def on_cask(cask_block)
|
def on_cask_stanza_block(stanza_block)
|
||||||
@cask_block = cask_block
|
stanzas = stanza_block.stanzas
|
||||||
add_offenses
|
ordered_stanzas = sort_stanzas(stanzas)
|
||||||
end
|
|
||||||
|
|
||||||
private
|
return if stanzas == ordered_stanzas
|
||||||
|
|
||||||
attr_reader :cask_block
|
stanzas.zip(ordered_stanzas).each do |stanza_before, stanza_after|
|
||||||
|
next if stanza_before == stanza_after
|
||||||
|
|
||||||
def_delegators :cask_block, :cask_node, :toplevel_stanzas,
|
add_offense(
|
||||||
:sorted_toplevel_stanzas
|
stanza_before.method_node,
|
||||||
|
message: format(MESSAGE, stanza: stanza_before.stanza_name),
|
||||||
|
) do |corrector|
|
||||||
|
next if part_of_ignored_node?(stanza_before.method_node)
|
||||||
|
|
||||||
def add_offenses
|
corrector.replace(
|
||||||
offending_stanzas.each do |stanza|
|
stanza_before.source_range_with_comments,
|
||||||
message = format(MESSAGE, stanza: stanza.stanza_name)
|
stanza_after.source_with_comments,
|
||||||
add_offense(stanza.source_range_with_comments, message: message) do |corrector|
|
)
|
||||||
correct_stanza_index = toplevel_stanzas.index(stanza)
|
|
||||||
correct_stanza = sorted_toplevel_stanzas[correct_stanza_index]
|
# Ignore node so that nested content is not auto-corrected and clobbered.
|
||||||
corrector.replace(stanza.source_range_with_comments,
|
ignore_node(stanza_before.method_node)
|
||||||
correct_stanza.source_with_comments)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def offending_stanzas
|
def on_new_investigation
|
||||||
stanza_pairs = toplevel_stanzas.zip(sorted_toplevel_stanzas)
|
super
|
||||||
stanza_pairs.each_with_object([]) do |stanza_pair, offending_stanzas|
|
|
||||||
stanza, sorted_stanza = *stanza_pair
|
ignored_nodes.clear
|
||||||
offending_stanzas << stanza if stanza != sorted_stanza
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def sort_stanzas(stanzas)
|
||||||
|
stanzas.sort do |stanza1, stanza2|
|
||||||
|
i1 = stanza1.stanza_index
|
||||||
|
i2 = stanza2.stanza_index
|
||||||
|
|
||||||
|
if i1 == i2
|
||||||
|
i1 = stanzas.index(stanza1)
|
||||||
|
i2 = stanzas.index(stanza2)
|
||||||
|
end
|
||||||
|
|
||||||
|
i1 - i2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stanza_order_index(stanza)
|
||||||
|
stanza_name = stanza.respond_to?(:method_name) ? stanza.method_name : stanza.stanza_name
|
||||||
|
RuboCop::Cask::Constants::STANZA_ORDER.index(stanza_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6373,6 +6373,8 @@ class RuboCop::AST::Node
|
|||||||
|
|
||||||
def method_node(param0=T.unsafe(nil)); end
|
def method_node(param0=T.unsafe(nil)); end
|
||||||
|
|
||||||
|
def on_system_block?(param0=T.unsafe(nil)); end
|
||||||
|
|
||||||
def val_node(param0=T.unsafe(nil)); end
|
def val_node(param0=T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -6504,12 +6506,61 @@ class RuboCop::Cask::AST::Stanza
|
|||||||
def zap?(); end
|
def zap?(); end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module RuboCop::Cop::Cask::CaskHelp
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
module RuboCop::Cop::Cask::CaskHelp
|
module RuboCop::Cop::Cask::CaskHelp
|
||||||
extend ::T::Private::Abstract::Hooks
|
extend ::T::Private::Abstract::Hooks
|
||||||
extend ::T::InterfaceWrapper::Helpers
|
extend ::T::InterfaceWrapper::Helpers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::Desc
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::HomepageUrlTrailingSlash
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::NoDslVersion
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::NoOverrides
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
module RuboCop::Cop::Cask::OnDescStanza
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
module RuboCop::Cop::Cask::OnHomepageStanza
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::OnSystemConditionals
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
module RuboCop::Cop::Cask::OnUrlStanza
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::StanzaGrouping
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::StanzaOrder
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Cask::Url
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Cask::Variables
|
class RuboCop::Cop::Cask::Variables
|
||||||
|
include ::RuboCop::Cop::CommentsHelp
|
||||||
def variable_assignment(param0); end
|
def variable_assignment(param0); end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -27,11 +27,11 @@ module CaskCop
|
|||||||
offenses = inspect_source(source)
|
offenses = inspect_source(source)
|
||||||
expect(offenses.size).to eq(expected_offenses.size)
|
expect(offenses.size).to eq(expected_offenses.size)
|
||||||
expected_offenses.zip(offenses).each do |expected, actual|
|
expected_offenses.zip(offenses).each do |expected, actual|
|
||||||
expect_offense(expected, actual)
|
expect_offense2(expected, actual)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def expect_offense(expected, actual)
|
def expect_offense2(expected, actual)
|
||||||
expect(actual.message).to eq(expected[:message])
|
expect(actual.message).to eq(expected[:message])
|
||||||
expect(actual.severity).to eq(expected[:severity])
|
expect(actual.severity).to eq(expected[:severity])
|
||||||
expect(actual.line).to eq(expected[:line])
|
expect(actual.line).to eq(expected[:line])
|
||||||
@ -39,8 +39,24 @@ module CaskCop
|
|||||||
expect(actual.location.source).to eq(expected[:source])
|
expect(actual.location.source).to eq(expected[:source])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: Replace with `expect_correction` from `rubocop-rspec`.
|
||||||
def expect_autocorrected_source(source, correct_source)
|
def expect_autocorrected_source(source, correct_source)
|
||||||
new_source = autocorrect_source(source)
|
correct_source = Array(correct_source).join("\n")
|
||||||
expect(new_source).to eq(Array(correct_source).join("\n"))
|
|
||||||
|
current_source = source
|
||||||
|
|
||||||
|
# RuboCop runs auto-correction in a loop to handle nested offenses.
|
||||||
|
loop do
|
||||||
|
current_source = autocorrect_source(current_source)
|
||||||
|
|
||||||
|
if (ignored_nodes = cop.instance_variable_get(:@ignored_nodes)) && ignored_nodes.any?
|
||||||
|
ignored_nodes.clear
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(current_source).to eq correct_source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,11 +3,9 @@
|
|||||||
require "rubocops/rubocop-cask"
|
require "rubocops/rubocop-cask"
|
||||||
require "test/rubocops/cask/shared_examples/cask_cop"
|
require "test/rubocops/cask/shared_examples/cask_cop"
|
||||||
|
|
||||||
describe RuboCop::Cop::Cask::StanzaOrder do
|
describe RuboCop::Cop::Cask::StanzaOrder, :config do
|
||||||
include CaskCop
|
include CaskCop
|
||||||
|
|
||||||
subject(:cop) { described_class.new }
|
|
||||||
|
|
||||||
context "when there is only one stanza" do
|
context "when there is only one stanza" do
|
||||||
let(:source) do
|
let(:source) do
|
||||||
<<~CASK
|
<<~CASK
|
||||||
@ -55,13 +53,13 @@ describe RuboCop::Cop::Cask::StanzaOrder do
|
|||||||
end
|
end
|
||||||
let(:expected_offenses) do
|
let(:expected_offenses) do
|
||||||
[{
|
[{
|
||||||
message: "Cask/StanzaOrder: `sha256` stanza out of order",
|
message: "`sha256` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 2,
|
line: 2,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "sha256 :no_check",
|
source: "sha256 :no_check",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `version` stanza out of order",
|
message: "`version` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 3,
|
line: 3,
|
||||||
column: 2,
|
column: 2,
|
||||||
@ -95,19 +93,19 @@ describe RuboCop::Cop::Cask::StanzaOrder do
|
|||||||
end
|
end
|
||||||
let(:expected_offenses) do
|
let(:expected_offenses) do
|
||||||
[{
|
[{
|
||||||
message: "Cask/StanzaOrder: `version` stanza out of order",
|
message: "`version` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 2,
|
line: 2,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "version :latest",
|
source: "version :latest",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `sha256` stanza out of order",
|
message: "`sha256` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 3,
|
line: 3,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "sha256 :no_check",
|
source: "sha256 :no_check",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `arch` stanza out of order",
|
message: "`arch` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 4,
|
line: 4,
|
||||||
column: 2,
|
column: 2,
|
||||||
@ -143,13 +141,13 @@ describe RuboCop::Cop::Cask::StanzaOrder do
|
|||||||
end
|
end
|
||||||
let(:expected_offenses) do
|
let(:expected_offenses) do
|
||||||
[{
|
[{
|
||||||
message: "Cask/StanzaOrder: `sha256` stanza out of order",
|
message: "`sha256` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 3,
|
line: 3,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "sha256 :no_check",
|
source: "sha256 :no_check",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `on_arch_conditional` stanza out of order",
|
message: "`on_arch_conditional` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 5,
|
line: 5,
|
||||||
column: 2,
|
column: 2,
|
||||||
@ -185,13 +183,13 @@ describe RuboCop::Cop::Cask::StanzaOrder do
|
|||||||
end
|
end
|
||||||
let(:expected_offenses) do
|
let(:expected_offenses) do
|
||||||
[{
|
[{
|
||||||
message: "Cask/StanzaOrder: `on_arch_conditional` stanza out of order",
|
message: "`on_arch_conditional` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 2,
|
line: 2,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: 'folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"',
|
source: 'folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"',
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `arch` stanza out of order",
|
message: "`arch` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 3,
|
line: 3,
|
||||||
column: 2,
|
column: 2,
|
||||||
@ -231,26 +229,26 @@ describe RuboCop::Cop::Cask::StanzaOrder do
|
|||||||
end
|
end
|
||||||
let(:expected_offenses) do
|
let(:expected_offenses) do
|
||||||
[{
|
[{
|
||||||
message: "Cask/StanzaOrder: `url` stanza out of order",
|
message: "`url` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 2,
|
line: 2,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "url 'https://foo.brew.sh/foo.zip'",
|
source: "url 'https://foo.brew.sh/foo.zip'",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `uninstall` stanza out of order",
|
message: "`uninstall` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 3,
|
line: 3,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "uninstall :quit => 'com.example.foo'," \
|
source: "uninstall :quit => 'com.example.foo'," \
|
||||||
"\n :kext => 'com.example.foo.kext'",
|
"\n :kext => 'com.example.foo.kext'",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `version` stanza out of order",
|
message: "`version` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 5,
|
line: 5,
|
||||||
column: 2,
|
column: 2,
|
||||||
source: "version :latest",
|
source: "version :latest",
|
||||||
}, {
|
}, {
|
||||||
message: "Cask/StanzaOrder: `sha256` stanza out of order",
|
message: "`sha256` stanza out of order",
|
||||||
severity: :convention,
|
severity: :convention,
|
||||||
line: 7,
|
line: 7,
|
||||||
column: 2,
|
column: 2,
|
||||||
@ -458,197 +456,108 @@ describe RuboCop::Cop::Cask::StanzaOrder do
|
|||||||
include_examples "autocorrects source"
|
include_examples "autocorrects source"
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: detect out-of-order stanzas in nested expressions
|
context "when `on_arch` blocks and their contents are out of order" do
|
||||||
context "when stanzas are nested in a conditional expression" do
|
|
||||||
let(:source) do
|
|
||||||
<<~CASK
|
|
||||||
cask 'foo' do
|
|
||||||
if true
|
|
||||||
sha256 :no_check
|
|
||||||
version :latest
|
|
||||||
end
|
|
||||||
end
|
|
||||||
CASK
|
|
||||||
end
|
|
||||||
|
|
||||||
include_examples "does not report any offenses"
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when `on_arch` blocks are out of order" do
|
|
||||||
let(:source) do
|
let(:source) do
|
||||||
<<~CASK
|
<<~CASK
|
||||||
cask 'foo' do
|
cask 'foo' do
|
||||||
on_intel do
|
on_intel do
|
||||||
url "https://foo.brew.sh/foo-intel.zip"
|
url "https://foo.brew.sh/foo-intel.zip"
|
||||||
sha256 :no_check
|
|
||||||
version :latest
|
|
||||||
end
|
|
||||||
|
|
||||||
|
version :latest
|
||||||
|
sha256 :no_check
|
||||||
|
end
|
||||||
on_arm do
|
on_arm do
|
||||||
url "https://foo.brew.sh/foo-arm.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
version :latest
|
version :latest
|
||||||
end
|
sha256 :no_check
|
||||||
|
|
||||||
name "Foo"
|
url "https://foo.brew.sh/foo-arm.zip"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
CASK
|
CASK
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:expected_offenses) do
|
|
||||||
[{
|
|
||||||
message: "Cask/StanzaOrder: `on_intel` stanza out of order",
|
|
||||||
severity: :convention,
|
|
||||||
line: 2,
|
|
||||||
column: 2,
|
|
||||||
source: "on_intel do\n url \"https://foo.brew.sh/foo-intel.zip\"\n sha256 :no_check\n version :latest\n end", # rubocop:disable Layout/LineLength
|
|
||||||
}, {
|
|
||||||
message: "Cask/StanzaOrder: `on_arm` stanza out of order",
|
|
||||||
severity: :convention,
|
|
||||||
line: 8,
|
|
||||||
column: 2,
|
|
||||||
source: "on_arm do\n url \"https://foo.brew.sh/foo-arm.zip\"\n sha256 :no_check\n version :latest\n end", # rubocop:disable Layout/LineLength
|
|
||||||
}]
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:correct_source) do
|
let(:correct_source) do
|
||||||
<<~CASK
|
<<~CASK
|
||||||
cask 'foo' do
|
cask 'foo' do
|
||||||
on_arm do
|
on_arm do
|
||||||
|
version :latest
|
||||||
|
sha256 :no_check
|
||||||
|
|
||||||
url "https://foo.brew.sh/foo-arm.zip"
|
url "https://foo.brew.sh/foo-arm.zip"
|
||||||
sha256 :no_check
|
|
||||||
version :latest
|
|
||||||
end
|
end
|
||||||
|
|
||||||
on_intel do
|
on_intel do
|
||||||
|
version :latest
|
||||||
|
|
||||||
|
sha256 :no_check
|
||||||
url "https://foo.brew.sh/foo-intel.zip"
|
url "https://foo.brew.sh/foo-intel.zip"
|
||||||
sha256 :no_check
|
|
||||||
version :latest
|
|
||||||
end
|
end
|
||||||
|
|
||||||
name "Foo"
|
|
||||||
end
|
end
|
||||||
CASK
|
CASK
|
||||||
end
|
end
|
||||||
|
|
||||||
include_examples "reports offenses"
|
|
||||||
include_examples "autocorrects source"
|
include_examples "autocorrects source"
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: detect out-of-order stanzas in nested expressions
|
it "registers an offense when `on_os` stanzas and their contents are out of order" do
|
||||||
context "when the on_arch and on_os stanzas are nested" do
|
expect_offense <<~CASK
|
||||||
let(:source) do
|
cask "foo" do
|
||||||
<<~CASK
|
on_ventura do
|
||||||
cask 'foo' do
|
^^^^^^^^^^^^^ `on_ventura` stanza out of order
|
||||||
on_arm do
|
sha256 "abc123"
|
||||||
url "https://foo.brew.sh/foo-arm-all.zip"
|
^^^^^^^^^^^^^^^ `sha256` stanza out of order
|
||||||
sha256 :no_check
|
version :latest
|
||||||
version :latest
|
^^^^^^^^^^^^^^^ `version` stanza out of order
|
||||||
end
|
url "https://foo.brew.sh/foo-ventura.zip"
|
||||||
|
|
||||||
on_intel do
|
|
||||||
on_ventura do
|
|
||||||
url "https://foo.brew.sh/foo-intel-ventura.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_mojave do
|
|
||||||
url "https://foo.brew.sh/foo-intel-mojave.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_catalina do
|
|
||||||
url "https://foo.brew.sh/foo-intel-catalina.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_big_sur do
|
|
||||||
url "https://foo.brew.sh/foo-intel-big-sur.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
|
|
||||||
version :latest
|
|
||||||
end
|
|
||||||
|
|
||||||
name "Foo"
|
|
||||||
end
|
end
|
||||||
CASK
|
on_catalina do
|
||||||
end
|
sha256 "def456"
|
||||||
|
^^^^^^^^^^^^^^^ `sha256` stanza out of order
|
||||||
include_examples "does not report any offenses"
|
version "0.7"
|
||||||
end
|
^^^^^^^^^^^^^ `version` stanza out of order
|
||||||
|
url "https://foo.brew.sh/foo-catalina.zip"
|
||||||
context "when the on_os stanzas are out of order" do
|
|
||||||
let(:source) do
|
|
||||||
<<~CASK
|
|
||||||
cask "foo" do
|
|
||||||
on_ventura do
|
|
||||||
url "https://foo.brew.sh/foo-ventura.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_catalina do
|
|
||||||
url "https://foo.brew.sh/foo-catalina.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_mojave do
|
|
||||||
url "https://foo.brew.sh/foo-mojave.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_big_sur do
|
|
||||||
url "https://foo.brew.sh/foo-big-sur.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
|
|
||||||
name "Foo"
|
|
||||||
end
|
end
|
||||||
CASK
|
on_mojave do
|
||||||
end
|
^^^^^^^^^^^^ `on_mojave` stanza out of order
|
||||||
|
version :latest
|
||||||
let(:expected_offenses) do
|
sha256 "ghi789"
|
||||||
[{
|
url "https://foo.brew.sh/foo-mojave.zip"
|
||||||
message: "Cask/StanzaOrder: `on_ventura` stanza out of order",
|
|
||||||
severity: :convention,
|
|
||||||
line: 2,
|
|
||||||
column: 2,
|
|
||||||
source: "on_ventura do\n url \"https://foo.brew.sh/foo-ventura.zip\"\n sha256 :no_check\n end",
|
|
||||||
}, {
|
|
||||||
message: "Cask/StanzaOrder: `on_mojave` stanza out of order",
|
|
||||||
severity: :convention,
|
|
||||||
line: 10,
|
|
||||||
column: 2,
|
|
||||||
source: "on_mojave do\n url \"https://foo.brew.sh/foo-mojave.zip\"\n sha256 :no_check\n end",
|
|
||||||
}, {
|
|
||||||
message: "Cask/StanzaOrder: `on_big_sur` stanza out of order",
|
|
||||||
severity: :convention,
|
|
||||||
line: 14,
|
|
||||||
column: 2,
|
|
||||||
source: "on_big_sur do\n url \"https://foo.brew.sh/foo-big-sur.zip\"\n sha256 :no_check\n end",
|
|
||||||
}]
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:correct_source) do
|
|
||||||
<<~CASK
|
|
||||||
cask "foo" do
|
|
||||||
on_mojave do
|
|
||||||
url "https://foo.brew.sh/foo-mojave.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_catalina do
|
|
||||||
url "https://foo.brew.sh/foo-catalina.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_big_sur do
|
|
||||||
url "https://foo.brew.sh/foo-big-sur.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
on_ventura do
|
|
||||||
url "https://foo.brew.sh/foo-ventura.zip"
|
|
||||||
sha256 :no_check
|
|
||||||
end
|
|
||||||
|
|
||||||
name "Foo"
|
|
||||||
end
|
end
|
||||||
CASK
|
on_big_sur do
|
||||||
end
|
^^^^^^^^^^^^^ `on_big_sur` stanza out of order
|
||||||
|
sha256 "jkl012"
|
||||||
|
^^^^^^^^^^^^^^^ `sha256` stanza out of order
|
||||||
|
version :latest
|
||||||
|
^^^^^^^^^^^^^^^ `version` stanza out of order
|
||||||
|
|
||||||
include_examples "reports offenses"
|
url "https://foo.brew.sh/foo-big-sur.zip"
|
||||||
include_examples "autocorrects source"
|
end
|
||||||
|
end
|
||||||
|
CASK
|
||||||
|
|
||||||
|
expect_correction <<~CASK
|
||||||
|
cask "foo" do
|
||||||
|
on_mojave do
|
||||||
|
version :latest
|
||||||
|
sha256 "ghi789"
|
||||||
|
url "https://foo.brew.sh/foo-mojave.zip"
|
||||||
|
end
|
||||||
|
on_catalina do
|
||||||
|
version "0.7"
|
||||||
|
sha256 "def456"
|
||||||
|
url "https://foo.brew.sh/foo-catalina.zip"
|
||||||
|
end
|
||||||
|
on_big_sur do
|
||||||
|
version :latest
|
||||||
|
sha256 "jkl012"
|
||||||
|
|
||||||
|
url "https://foo.brew.sh/foo-big-sur.zip"
|
||||||
|
end
|
||||||
|
on_ventura do
|
||||||
|
version :latest
|
||||||
|
sha256 "abc123"
|
||||||
|
url "https://foo.brew.sh/foo-ventura.zip"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CASK
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user