Merge pull request #10300 from jonchang/rubocop-v1-api

rubocops: migrate to rubocop v1 API
This commit is contained in:
Jonathan Chang 2021-01-13 21:20:55 +11:00 committed by GitHub
commit 71f7ef0058
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1655 additions and 1921 deletions

View File

@ -11,19 +11,15 @@ module RuboCop
module Cask module Cask
# This cop audits `desc` in casks. # This cop audits `desc` in casks.
# See the {DescHelper} module for details of the checks. # See the {DescHelper} module for details of the checks.
class Desc < Cop class Desc < Base
include OnDescStanza include OnDescStanza
include DescHelper include DescHelper
extend AutoCorrector
def on_desc_stanza(stanza) def on_desc_stanza(stanza)
name = cask_block.header.cask_token @name = cask_block.header.cask_token
desc_call = stanza.stanza_node desc_call = stanza.stanza_node
audit_desc(:cask, name, desc_call) audit_desc(:cask, @name, desc_call)
end
def autocorrect(node)
name = cask_block.header.cask_token
autocorrect_desc(node, name)
end end
end end
end end

View File

@ -9,8 +9,9 @@ module RuboCop
module Cask module Cask
# This cop checks that a cask's homepage ends with a slash # This cop checks that a cask's homepage ends with a slash
# if it does not have a path component. # if it does not have a path component.
class HomepageUrlTrailingSlash < Cop class HomepageUrlTrailingSlash < Base
include OnHomepageStanza include OnHomepageStanza
extend AutoCorrector
MSG_NO_SLASH = "'%<url>s' must have a slash after the domain." MSG_NO_SLASH = "'%<url>s' must have a slash after the domain."
@ -26,19 +27,14 @@ module RuboCop
return unless url&.match?(%r{^.+://[^/]+$}) return unless url&.match?(%r{^.+://[^/]+$})
add_offense(url_node, location: :expression, domain = URI(url_node.str_content).host
message: format(MSG_NO_SLASH, url: url))
end
def autocorrect(node)
domain = URI(node.str_content).host
# This also takes URLs like 'https://example.org?path' # This also takes URLs like 'https://example.org?path'
# and 'https://example.org#path' into account. # and 'https://example.org#path' into account.
corrected_source = node.source.sub("://#{domain}", "://#{domain}/") corrected_source = url_node.source.sub("://#{domain}", "://#{domain}/")
lambda do |corrector| add_offense(url_node.loc.expression, message: format(MSG_NO_SLASH, url: url)) do |corrector|
corrector.replace(node.source_range, corrected_source) corrector.replace(url_node.source_range, corrected_source)
end end
end end
end end

View File

@ -18,10 +18,11 @@ module RuboCop
# cask 'foo' do # cask 'foo' do
# ... # ...
# end # end
class NoDslVersion < Cop class NoDslVersion < Base
extend T::Sig extend T::Sig
extend Forwardable extend Forwardable
extend AutoCorrector
include CaskHelp include CaskHelp
MESSAGE = "Use `%<preferred>s` instead of `%<current>s`" MESSAGE = "Use `%<preferred>s` instead of `%<current>s`"
@ -33,13 +34,6 @@ module RuboCop
offense offense
end end
def autocorrect(method_node)
@cask_header = cask_header(method_node)
lambda do |corrector|
corrector.replace(header_range, preferred_header_str)
end
end
private private
def_delegator :@cask_header, :source_range, :header_range def_delegator :@cask_header, :source_range, :header_range
@ -54,8 +48,9 @@ module RuboCop
end end
def offense def offense
add_offense(@cask_header.method_node, location: header_range, add_offense(header_range, message: error_msg) do |corrector|
message: error_msg) corrector.replace(header_range, preferred_header_str)
end
end end
sig { returns(String) } sig { returns(String) }

View File

@ -8,8 +8,9 @@ module RuboCop
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.
# @see https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/readme.md#stanza-order # @see https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/readme.md#stanza-order
class StanzaGrouping < Cop class StanzaGrouping < Base
extend Forwardable extend Forwardable
extend AutoCorrector
include CaskHelp include CaskHelp
include RangeHelp include RangeHelp
@ -25,17 +26,6 @@ module RuboCop
add_offenses add_offenses
end end
def autocorrect(range)
lambda do |corrector|
case line_ops[range.line - 1]
when :insert
corrector.insert_before(range, "\n")
when :remove
corrector.remove(range)
end
end
end
private private
attr_reader :cask_block, :line_ops attr_reader :cask_block, :line_ops
@ -79,20 +69,24 @@ module RuboCop
def add_offense_missing_line(stanza) def add_offense_missing_line(stanza)
line_index = index_of_line_after(stanza) line_index = index_of_line_after(stanza)
line_ops[line_index] = :insert line_ops[line_index] = :insert
add_offense(line_index, message: MISSING_LINE_MSG) add_offense(line_index, message: MISSING_LINE_MSG) do |corrector|
corrector.insert_before(@range, "\n")
end
end end
def add_offense_extra_line(stanza) def add_offense_extra_line(stanza)
line_index = index_of_line_after(stanza) line_index = index_of_line_after(stanza)
line_ops[line_index] = :remove line_ops[line_index] = :remove
add_offense(line_index, message: EXTRA_LINE_MSG) add_offense(line_index, message: EXTRA_LINE_MSG) do |corrector|
corrector.remove(@range)
end
end end
def add_offense(line_index, message:) def add_offense(line_index, message:)
line_length = [processed_source[line_index].size, 1].max line_length = [processed_source[line_index].size, 1].max
range = source_range(processed_source.buffer, line_index + 1, 0, @range = source_range(processed_source.buffer, line_index + 1, 0,
line_length) line_length)
super(range, location: range, message: message) super(@range, message: message)
end end
end end
end end

View File

@ -8,8 +8,9 @@ module RuboCop
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.
# @see https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/readme.md#stanza-order # @see https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/readme.md#stanza-order
class StanzaOrder < Cop class StanzaOrder < Base
extend Forwardable extend Forwardable
extend AutoCorrector
include CaskHelp include CaskHelp
MESSAGE = "`%<stanza>s` stanza out of order" MESSAGE = "`%<stanza>s` stanza out of order"
@ -19,15 +20,6 @@ module RuboCop
add_offenses add_offenses
end end
def autocorrect(stanza)
lambda do |corrector|
correct_stanza_index = toplevel_stanzas.index(stanza)
correct_stanza = sorted_toplevel_stanzas[correct_stanza_index]
corrector.replace(stanza.source_range_with_comments,
correct_stanza.source_with_comments)
end
end
private private
attr_reader :cask_block attr_reader :cask_block
@ -38,8 +30,12 @@ module RuboCop
def add_offenses def add_offenses
offending_stanzas.each do |stanza| offending_stanzas.each do |stanza|
message = format(MESSAGE, stanza: stanza.stanza_name) message = format(MESSAGE, stanza: stanza.stanza_name)
add_offense(stanza, location: stanza.source_range_with_comments, add_offense(stanza.source_range_with_comments, message: message) do |corrector|
message: message) correct_stanza_index = toplevel_stanzas.index(stanza)
correct_stanza = sorted_toplevel_stanzas[correct_stanza_index]
corrector.replace(stanza.source_range_with_comments,
correct_stanza.source_with_comments)
end
end end
end end

View File

@ -28,7 +28,6 @@ module RuboCop
return if checksum.nil? return if checksum.nil?
if regex_match_group(checksum, /^$/) if regex_match_group(checksum, /^$/)
@offense_source_range = @offensive_node.source_range
problem "sha256 is empty" problem "sha256 is empty"
return return
end end
@ -39,7 +38,7 @@ module RuboCop
return unless regex_match_group(checksum, /[^a-f0-9]+/i) return unless regex_match_group(checksum, /[^a-f0-9]+/i)
problem "sha256 contains invalid characters" add_offense(@offensive_source_range, message: "sha256 contains invalid characters")
end end
end end
@ -47,6 +46,8 @@ module RuboCop
# #
# @api private # @api private
class ChecksumCase < FormulaCop class ChecksumCase < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil? return if body_node.nil?
@ -56,15 +57,11 @@ module RuboCop
next if checksum.nil? next if checksum.nil?
next unless regex_match_group(checksum, /[A-F]+/) next unless regex_match_group(checksum, /[A-F]+/)
problem "sha256 should be lowercase" add_offense(@offensive_source_range, message: "sha256 should be lowercase") do |corrector|
end correction = @offensive_node.source.downcase
end corrector.insert_before(@offensive_node.source_range, correction)
corrector.remove(@offensive_node.source_range)
def autocorrect(node) end
lambda do |corrector|
correction = node.source.downcase
corrector.insert_before(node.source_range, correction)
corrector.remove(node.source_range)
end end
end end
end end

View File

@ -10,6 +10,8 @@ module RuboCop
# #
# @api private # @api private
class ClassName < FormulaCop class ClassName < FormulaCop
extend AutoCorrector
DEPRECATED_CLASSES = %w[ DEPRECATED_CLASSES = %w[
GithubGistFormula GithubGistFormula
ScriptFileFormula ScriptFileFormula
@ -20,12 +22,8 @@ module RuboCop
parent_class = class_name(parent_class_node) parent_class = class_name(parent_class_node)
return unless DEPRECATED_CLASSES.include?(parent_class) return unless DEPRECATED_CLASSES.include?(parent_class)
problem "#{parent_class} is deprecated, use Formula instead" problem "#{parent_class} is deprecated, use Formula instead" do |corrector|
end corrector.replace(parent_class_node.source_range, "Formula")
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, "Formula")
end end
end end
end end
@ -34,6 +32,8 @@ module RuboCop
# #
# @api private # @api private
class Test < FormulaCop class Test < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
test = find_block(body_node, :test) test = find_block(body_node, :test)
return unless test return unless test
@ -49,31 +49,17 @@ module RuboCop
p1, p2 = params p1, p2 = params
if match = string_content(p1).match(%r{(/usr/local/(s?bin))}) if match = string_content(p1).match(%r{(/usr/local/(s?bin))})
offending_node(p1) offending_node(p1)
problem "use \#{#{match[2]}} instead of #{match[1]} in #{node}" problem "use \#{#{match[2]}} instead of #{match[1]} in #{node}" do |corrector|
corrector.replace(p1.source_range, p1.source.sub(match[1], "\#{#{match[2]}}"))
end
end end
if node == :shell_output && node_equals?(p2, 0) if node == :shell_output && node_equals?(p2, 0)
offending_node(p2) offending_node(p2)
problem "Passing 0 to shell_output() is redundant" problem "Passing 0 to shell_output() is redundant" do |corrector|
end corrector.remove(range_with_surrounding_comma(range_with_surrounding_space(range: p2.source_range,
end side: :left)))
end end
def autocorrect(node)
lambda do |corrector|
case node.type
when :str, :dstr
# Rubocop: intentionally outputted non-interpolated strings
corrector.replace(node.source_range,
node.source.to_s.sub(%r{(/usr/local/(s?bin))},
'#{\2}')) # rubocop:disable Lint/InterpolationCheck
when :int
corrector.remove(
range_with_surrounding_comma(
range_with_surrounding_space(range: node.source_range,
side: :left),
),
)
end end
end end
end end

View File

@ -12,6 +12,8 @@ module RuboCop
# - `component_precedence_list` has component hierarchy in a nested list # - `component_precedence_list` has component hierarchy in a nested list
# where each sub array contains components' details which are at same precedence level # where each sub array contains components' details which are at same precedence level
class ComponentsOrder < FormulaCop class ComponentsOrder < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
@present_components, @offensive_nodes = check_order(FORMULA_COMPONENT_PRECEDENCE_LIST, body_node) @present_components, @offensive_nodes = check_order(FORMULA_COMPONENT_PRECEDENCE_LIST, body_node)
@ -27,7 +29,6 @@ module RuboCop
if on_macos_blocks.length > 1 if on_macos_blocks.length > 1
@offensive_node = on_macos_blocks.second @offensive_node = on_macos_blocks.second
@offense_source_range = on_macos_blocks.second.source_range
problem "there can only be one `on_macos` block in a formula." problem "there can only be one `on_macos` block in a formula."
end end
@ -37,7 +38,6 @@ module RuboCop
if on_linux_blocks.length > 1 if on_linux_blocks.length > 1
@offensive_node = on_linux_blocks.second @offensive_node = on_linux_blocks.second
@offense_source_range = on_linux_blocks.second.source_range
problem "there can only be one `on_linux` block in a formula." problem "there can only be one `on_linux` block in a formula."
end end
@ -58,7 +58,6 @@ module RuboCop
end end
@offensive_node = resource_block @offensive_node = resource_block
@offense_source_range = resource_block.source_range
next if on_macos_blocks.length.zero? && on_linux_blocks.length.zero? next if on_macos_blocks.length.zero? && on_linux_blocks.length.zero?
@ -122,7 +121,6 @@ module RuboCop
valid_node ||= on_os_allowed_methods.include? child.method_name.to_s valid_node ||= on_os_allowed_methods.include? child.method_name.to_s
@offensive_node = child @offensive_node = child
@offense_source_range = child.source_range
next if valid_node next if valid_node
problem "`#{on_os_block.method_name}` cannot include `#{child.method_name}`. " \ problem "`#{on_os_block.method_name}` cannot include `#{child.method_name}`. " \
@ -130,17 +128,6 @@ module RuboCop
end end
end end
# {autocorrect} gets called just after {component_problem}.
def autocorrect(_node)
return if @offensive_nodes.nil?
succeeding_node = @offensive_nodes[0]
preceding_node = @offensive_nodes[1]
lambda do |corrector|
reorder_components(corrector, succeeding_node, preceding_node)
end
end
# Reorder two nodes in the source, using the corrector instance in autocorrect method. # Reorder two nodes in the source, using the corrector instance in autocorrect method.
# Components of same type are grouped together when rewriting the source. # Components of same type are grouped together when rewriting the source.
# Linebreaks are introduced if components are of two different methods/blocks/multilines. # Linebreaks are introduced if components are of two different methods/blocks/multilines.
@ -201,13 +188,15 @@ module RuboCop
nil nil
end end
# Method to format message for reporting component precedence violations. # Method to report and correct component precedence violations.
def component_problem(c1, c2) def component_problem(c1, c2)
return if tap_style_exception? :components_order_exceptions return if tap_style_exception? :components_order_exceptions
problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \ problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \
"should be put before `#{format_component(c2)}` " \ "should be put before `#{format_component(c2)}` " \
"(line #{line_number(c2)})" "(line #{line_number(c2)})" do |corrector|
reorder_components(corrector, c1, c2)
end
end end
# Node pattern method to match # Node pattern method to match

View File

@ -9,6 +9,8 @@ module RuboCop
module FormulaAudit module FormulaAudit
# This cop audits versioned formulae for `conflicts_with`. # This cop audits versioned formulae for `conflicts_with`.
class Conflicts < FormulaCop class Conflicts < FormulaCop
extend AutoCorrector
MSG = "Versioned formulae should not use `conflicts_with`. " \ MSG = "Versioned formulae should not use `conflicts_with`. " \
"Use `keg_only :versioned_formula` instead." "Use `keg_only :versioned_formula` instead."
@ -19,31 +21,29 @@ module RuboCop
reason = parameters(conflicts_with_call).last.values.first reason = parameters(conflicts_with_call).last.values.first
offending_node(reason) offending_node(reason)
name = Regexp.new(@formula_name, Regexp::IGNORECASE) name = Regexp.new(@formula_name, Regexp::IGNORECASE)
reason = string_content(reason).sub(name, "") reason_text = string_content(reason).sub(name, "")
first_word = reason.split.first first_word = reason_text.split.first
if reason.match?(/\A[A-Z]/) if reason_text.match?(/\A[A-Z]/)
problem "'#{first_word}' from the `conflicts_with` reason should be '#{first_word.downcase}'." problem "'#{first_word}' from the `conflicts_with` reason "\
"should be '#{first_word.downcase}'." do |corrector|
reason_text[0] = reason_text[0].downcase
corrector.replace(reason.source_range, "\"#{reason_text}\"")
end
end end
next unless reason_text.end_with?(".")
problem "`conflicts_with` reason should not end with a period." if reason.end_with?(".") problem "`conflicts_with` reason should not end with a period." do |corrector|
corrector.replace(reason.source_range, "\"#{reason_text.chop}\"")
end
end end
return unless versioned_formula? return unless versioned_formula?
problem MSG if !tap_style_exception?(:versioned_formulae_conflicts_allowlist) && if !tap_style_exception?(:versioned_formulae_conflicts_allowlist) && method_called_ever?(body_node,
method_called_ever?(body_node, :conflicts_with) :conflicts_with)
end problem MSG do |corrector|
corrector.replace(@offensive_node.source_range, "keg_only :versioned_formula")
def autocorrect(node)
lambda do |corrector|
if versioned_formula?
corrector.replace(node.source_range, "keg_only :versioned_formula")
else
reason = string_content(node)
reason[0] = reason[0].downcase
reason = reason.delete_suffix(".")
corrector.replace(node.source_range, "\"#{reason}\"")
end end
end end
end end

View File

@ -11,6 +11,8 @@ module RuboCop
# precedence order: # precedence order:
# build-time > test > normal > recommended > optional # build-time > test > normal > recommended > optional
class DependencyOrder < FormulaCop class DependencyOrder < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
check_dependency_nodes_order(body_node) check_dependency_nodes_order(body_node)
check_uses_from_macos_nodes_order(body_node) check_uses_from_macos_nodes_order(body_node)
@ -89,17 +91,26 @@ module RuboCop
# Verify actual order of sorted `depends_on` nodes in source code; # Verify actual order of sorted `depends_on` nodes in source code;
# raise RuboCop problem otherwise. # raise RuboCop problem otherwise.
def verify_order_in_source(ordered) def verify_order_in_source(ordered)
ordered.each_with_index do |dependency_node_1, idx| ordered.each_with_index do |node_1, idx|
l1 = line_number(dependency_node_1) l1 = line_number(node_1)
dependency_node_2 = nil l2 = nil
ordered.drop(idx+1).each do |node2| node_2 = nil
l2 = line_number(node2) ordered.drop(idx + 1).each do |test_node|
dependency_node_2 = node2 if l2 < l1 l2 = line_number(test_node)
node_2 = test_node if l2 < l1
end end
next unless dependency_node_2 next unless node_2
@offensive_nodes = [dependency_node_1, dependency_node_2] offending_node(node_1)
component_problem dependency_node_1, dependency_node_2
problem "dependency \"#{dependency_name(node_1)}\" (line #{l1}) should be put before dependency "\
"\"#{dependency_name(node_2)}\" (line #{l2})" do |corrector|
indentation = " " * (start_column(node_2) - line_start_column(node_2))
line_breaks = "\n"
corrector.insert_before(node_2.source_range,
node_1.source + line_breaks + indentation)
corrector.remove(range_with_surrounding_space(range: node_1.source_range, side: :left))
end
end end
end end
@ -150,31 +161,6 @@ module RuboCop
match_node = dependency_name_node(dependency_node).to_a.first match_node = dependency_name_node(dependency_node).to_a.first
string_content(match_node) if match_node string_content(match_node) if match_node
end end
def autocorrect(_node)
succeeding_node = @offensive_nodes[0]
preceding_node = @offensive_nodes[1]
lambda do |corrector|
reorder_components(corrector, succeeding_node, preceding_node)
end
end
private
def component_problem(c1, c2)
offending_node(c1)
problem "dependency \"#{dependency_name(c1)}\" " \
"(line #{line_number(c1)}) should be put before dependency "\
"\"#{dependency_name(c2)}\" (line #{line_number(c2)})"
end
# Reorder two nodes in the source, using the corrector instance in the {autocorrect} method.
def reorder_components(corrector, node1, node2)
indentation = " " * (start_column(node2) - line_start_column(node2))
line_breaks = "\n"
corrector.insert_before(node2.source_range, node1.source + line_breaks + indentation)
corrector.remove(range_with_surrounding_space(range: node1.source_range, side: :left))
end
end end
end end
end end

View File

@ -8,6 +8,8 @@ module RuboCop
module FormulaAudit module FormulaAudit
# This cop audits `deprecate!` and `disable!` dates. # This cop audits `deprecate!` and `disable!` dates.
class DeprecateDisableDate < FormulaCop class DeprecateDisableDate < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
[:deprecate!, :disable!].each do |method| [:deprecate!, :disable!].each do |method|
node = find_node_method_by_name(body_node, method) node = find_node_method_by_name(body_node, method)
@ -19,18 +21,13 @@ module RuboCop
rescue ArgumentError rescue ArgumentError
fixed_date_string = Date.parse(string_content(date_node)).iso8601 fixed_date_string = Date.parse(string_content(date_node)).iso8601
offending_node(date_node) offending_node(date_node)
problem "Use `#{fixed_date_string}` to comply with ISO 8601" problem "Use `#{fixed_date_string}` to comply with ISO 8601" do |corrector|
corrector.replace(date_node.source_range, "\"#{fixed_date_string}\"")
end
end end
end end
end end
def autocorrect(node)
lambda do |corrector|
fixed_fixed_date_string = Date.parse(string_content(node)).iso8601
corrector.replace(node.source_range, "\"#{fixed_fixed_date_string}\"")
end
end
def_node_search :date, <<~EOS def_node_search :date, <<~EOS
(pair (sym :date) $str) (pair (sym :date) $str)
EOS EOS
@ -38,6 +35,8 @@ module RuboCop
# This cop audits `deprecate!` and `disable!` reasons. # This cop audits `deprecate!` and `disable!` reasons.
class DeprecateDisableReason < FormulaCop class DeprecateDisableReason < FormulaCop
extend AutoCorrector
PUNCTUATION_MARKS = %w[. ! ?].freeze PUNCTUATION_MARKS = %w[. ! ?].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
@ -54,9 +53,17 @@ module RuboCop
offending_node(reason_node) offending_node(reason_node)
reason_string = string_content(reason_node) reason_string = string_content(reason_node)
problem "Do not start the reason with `it`" if reason_string.start_with?("it ") if reason_string.start_with?("it ")
problem "Do not start the reason with `it`" do |corrector|
corrector.replace(@offensive_node.source_range, "\"#{reason_string[3..]}\"")
end
end
problem "Do not end the reason with a punctuation mark" if PUNCTUATION_MARKS.include?(reason_string[-1]) if PUNCTUATION_MARKS.include?(reason_string[-1])
problem "Do not end the reason with a punctuation mark" do |corrector|
corrector.replace(@offensive_node.source_range, "\"#{reason_string.chop}\"")
end
end
end end
next if reason_found next if reason_found
@ -70,17 +77,6 @@ module RuboCop
end end
end end
def autocorrect(node)
return unless node.str_type?
lambda do |corrector|
reason = string_content(node)
reason = reason[3..] if reason.start_with?("it ")
reason.chop! if PUNCTUATION_MARKS.include?(reason[-1])
corrector.replace(node.source_range, "\"#{reason}\"")
end
end
def_node_search :reason, <<~EOS def_node_search :reason, <<~EOS
(pair (sym :because) ${str sym}) (pair (sym :because) ${str sym})
EOS EOS

View File

@ -18,7 +18,7 @@ module RuboCop
# Superclass for all formula cops. # Superclass for all formula cops.
# #
# @api private # @api private
class FormulaCop < Cop class FormulaCop < Base
include RangeHelp include RangeHelp
include HelperFunctions include HelperFunctions
@ -71,19 +71,16 @@ module RuboCop
next unless method_node.method_name == method_name next unless method_node.method_name == method_name
@offensive_node = method_node @offensive_node = method_node
@offense_source_range = method_node.source_range
return method_node return method_node
end end
# If not found then, parent node becomes the offensive node # If not found then, parent node becomes the offensive node
@offensive_node = node.parent @offensive_node = node.parent
@offense_source_range = node.parent.source_range
nil nil
end end
# Sets the given node as the offending node when required in custom cops. # Sets the given node as the offending node when required in custom cops.
def offending_node(node) def offending_node(node)
@offensive_node = node @offensive_node = node
@offense_source_range = node.source_range
end end
# Returns an array of method call nodes matching method_name inside node with depth first order (child nodes). # Returns an array of method call nodes matching method_name inside node with depth first order (child nodes).
@ -142,7 +139,6 @@ module RuboCop
next if method.receiver.const_name != instance && next if method.receiver.const_name != instance &&
!(method.receiver.send_type? && method.receiver.method_name == instance) !(method.receiver.send_type? && method.receiver.method_name == instance)
@offense_source_range = method.source_range
@offensive_node = method @offensive_node = method
return true unless block_given? return true unless block_given?
@ -160,7 +156,6 @@ module RuboCop
next if method_node.receiver.const_name != name && next if method_node.receiver.const_name != name &&
!(method_node.receiver.send_type? && method_node.receiver.method_name == name) !(method_node.receiver.send_type? && method_node.receiver.method_name == name)
@offense_source_range = method_node.receiver.source_range
@offensive_node = method_node.receiver @offensive_node = method_node.receiver
return true unless block_given? return true unless block_given?
@ -179,7 +174,6 @@ module RuboCop
end end
return if idx.nil? return if idx.nil?
@offense_source_range = dependency_nodes[idx].source_range
@offensive_node = dependency_nodes[idx] @offensive_node = dependency_nodes[idx]
end end
@ -207,10 +201,7 @@ module RuboCop
type_match = false type_match = false
end end
if type_match || name_match @offensive_node = node if type_match || name_match
@offensive_node = node
@offense_source_range = node.source_range
end
type_match && name_match type_match && name_match
end end
@ -223,7 +214,6 @@ module RuboCop
next unless const_node.const_name == const_name next unless const_node.const_name == const_name
@offensive_node = const_node @offensive_node = const_node
@offense_source_range = const_node.source_range
yield const_node if block_given? yield const_node if block_given?
return true return true
end end
@ -259,12 +249,10 @@ module RuboCop
next if block_node.method_name != block_name next if block_node.method_name != block_name
@offensive_node = block_node @offensive_node = block_node
@offense_source_range = block_node.source_range
return block_node return block_node
end end
# If not found then, parent node becomes the offensive node # If not found then, parent node becomes the offensive node
@offensive_node = node.parent @offensive_node = node.parent
@offense_source_range = node.parent.source_range
nil nil
end end
@ -299,14 +287,12 @@ module RuboCop
next if method_name != def_method_name && method_name.present? next if method_name != def_method_name && method_name.present?
@offensive_node = def_node @offensive_node = def_node
@offense_source_range = def_node.source_range
return def_node return def_node
end end
return if node.parent.nil? return if node.parent.nil?
# If not found then, parent node becomes the offensive node # If not found then, parent node becomes the offensive node
@offensive_node = node.parent @offensive_node = node.parent
@offense_source_range = node.parent.source_range
nil nil
end end
@ -317,7 +303,6 @@ module RuboCop
next unless call_node.method_name == method_name next unless call_node.method_name == method_name
@offensive_node = call_node @offensive_node = call_node
@offense_source_range = call_node.source_range
return true return true
end end
false false
@ -345,7 +330,6 @@ module RuboCop
next unless call_node.method_name == method_name next unless call_node.method_name == method_name
@offensive_node = call_node @offensive_node = call_node
@offense_source_range = call_node.source_range
return true return true
end end
false false
@ -365,7 +349,6 @@ module RuboCop
def component_precedes?(first_node, next_node) def component_precedes?(first_node, next_node)
return false if line_number(first_node) < line_number(next_node) return false if line_number(first_node) < line_number(next_node)
@offense_source_range = first_node.source_range
@offensive_node = first_node @offensive_node = first_node
true true
end end
@ -394,7 +377,6 @@ module RuboCop
def parameters_passed?(method_node, *params) def parameters_passed?(method_node, *params)
method_params = parameters(method_node) method_params = parameters(method_node)
@offensive_node = method_node @offensive_node = method_node
@offense_source_range = method_node.source_range
params.all? do |given_param| params.all? do |given_param|
method_params.any? do |method_param| method_params.any? do |method_param|
if given_param.instance_of?(Regexp) if given_param.instance_of?(Regexp)
@ -420,9 +402,8 @@ module RuboCop
# Yields to a block with comment text as parameter. # Yields to a block with comment text as parameter.
def audit_comments def audit_comments
@processed_source.comments.each do |comment_node| processed_source.comments.each do |comment_node|
@offensive_node = comment_node @offensive_node = comment_node
@offense_source_range = :expression
yield comment_node.text yield comment_node.text
end end
end end
@ -435,7 +416,6 @@ module RuboCop
# Returns the class node's name, or nil if not a class node. # Returns the class node's name, or nil if not a class node.
def class_name(node) def class_name(node)
@offensive_node = node @offensive_node = node
@offense_source_range = node.source_range
node.const_name node.const_name
end end

View File

@ -12,14 +12,12 @@ module RuboCop
# See the {DescHelper} module for details of the checks. # See the {DescHelper} module for details of the checks.
class Desc < FormulaCop class Desc < FormulaCop
include DescHelper include DescHelper
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
@name = @formula_name
desc_call = find_node_method_by_name(body_node, :desc) desc_call = find_node_method_by_name(body_node, :desc)
audit_desc(:formula, @formula_name, desc_call) audit_desc(:formula, @name, desc_call)
end
def autocorrect(node)
autocorrect_desc(node, @formula_name)
end end
end end
end end

View File

@ -8,19 +8,23 @@ module RuboCop
module FormulaAudit module FormulaAudit
# This cop audits the `homepage` URL in formulae. # This cop audits the `homepage` URL in formulae.
class Homepage < FormulaCop class Homepage < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
homepage_node = find_node_method_by_name(body_node, :homepage) homepage_node = find_node_method_by_name(body_node, :homepage)
homepage = if homepage_node
string_content(parameters(homepage_node).first) if homepage_node.nil?
else problem "Formula should have a homepage."
"" return
end end
problem "Formula should have a homepage." if homepage_node.nil? || homepage.empty? homepage_parameter_node = parameters(homepage_node).first
offending_node(homepage_parameter_node)
homepage = string_content(homepage_parameter_node)
unless homepage.match?(%r{^https?://}) problem "Formula should have a homepage." if homepage.empty?
problem "The homepage should start with http or https (URL is #{homepage})."
end problem "The homepage should start with http or https." unless homepage.match?(%r{^https?://})
case homepage case homepage
# Freedesktop is complicated to handle - It has SSL/TLS, but only on certain subdomains. # Freedesktop is complicated to handle - It has SSL/TLS, but only on certain subdomains.
@ -29,25 +33,34 @@ module RuboCop
# "Software" is redirected to https://wiki.freedesktop.org/www/Software/project_name # "Software" is redirected to https://wiki.freedesktop.org/www/Software/project_name
when %r{^http://((?:www|nice|libopenraw|liboil|telepathy|xorg)\.)?freedesktop\.org/(?:wiki/)?} when %r{^http://((?:www|nice|libopenraw|liboil|telepathy|xorg)\.)?freedesktop\.org/(?:wiki/)?}
if homepage.include?("Software") if homepage.include?("Software")
problem "#{homepage} should be styled `https://wiki.freedesktop.org/www/Software/project_name`" problem "Freedesktop homepages should be styled "\
"`https://wiki.freedesktop.org/www/Software/project_name`"
else else
problem "#{homepage} should be styled `https://wiki.freedesktop.org/project_name`" problem "Freedesktop homepages should be styled `https://wiki.freedesktop.org/project_name`"
end end
# Google Code homepages should end in a slash # Google Code homepages should end in a slash
when %r{^https?://code\.google\.com/p/[^/]+[^/]$} when %r{^https?://code\.google\.com/p/[^/]+[^/]$}
problem "#{homepage} should end with a slash" problem "Google Code homepages should end with a slash" do |corrector|
corrector.replace(homepage_parameter_node.source_range, "\"#{homepage}/\"")
end
when %r{^http://([^/]*)\.(sf|sourceforge)\.net(/|$)} when %r{^http://([^/]*)\.(sf|sourceforge)\.net(/|$)}
problem "#{homepage} should be `https://#{Regexp.last_match(1)}.sourceforge.io/`" fixed = "https://#{Regexp.last_match(1)}.sourceforge.io/"
problem "Sourceforge homepages should be `#{fixed}`" do |corrector|
corrector.replace(homepage_parameter_node.source_range, "\"#{fixed}\"")
end
when /readthedocs\.org/ when /readthedocs\.org/
offending_node(parameters(homepage_node).first) fixed = homepage.sub("readthedocs.org", "readthedocs.io")
problem "#{homepage} should be `#{homepage.sub("readthedocs.org", "readthedocs.io")}`" problem "Readthedocs homepages should be `#{fixed}`" do |corrector|
corrector.replace(homepage_parameter_node.source_range, "\"#{fixed}\"")
end
when %r{^https://github.com.*\.git} when %r{^https://github.com.*\.git}
offending_node(parameters(homepage_node).first) problem "GitHub homepages should not end with .git" do |corrector|
problem "GitHub homepages (`#{homepage}`) should not end with .git" corrector.replace(homepage_parameter_node.source_range, "\"#{homepage.delete_suffix(".git")}\"")
end
# People will run into mixed content sometimes, but we should enforce and then add # People will run into mixed content sometimes, but we should enforce and then add
# exemptions as they are discovered. Treat mixed content on homepages as a bug. # exemptions as they are discovered. Treat mixed content on homepages as a bug.
@ -81,20 +94,9 @@ module RuboCop
%r{^http://code\.google\.com/}, %r{^http://code\.google\.com/},
%r{^http://bitbucket\.org/}, %r{^http://bitbucket\.org/},
%r{^http://(?:[^/]*\.)?archive\.org} %r{^http://(?:[^/]*\.)?archive\.org}
problem "Please use https:// for #{homepage}" problem "Please use https:// for #{homepage}" do |corrector|
end corrector.replace(homepage_parameter_node.source_range, "\"#{homepage.sub("http", "https")}\"")
end end
def autocorrect(node)
lambda do |corrector|
return if node.nil?
homepage = string_content(node).dup
return if homepage.nil? || homepage.empty?
homepage.sub!("readthedocs.org", "readthedocs.io")
homepage.delete_suffix!(".git") if homepage.start_with?("https://github.com")
corrector.replace(node.source_range, "\"#{homepage}\"")
end end
end end
end end

View File

@ -10,6 +10,8 @@ module RuboCop
# #
# @api private # @api private
class KegOnly < FormulaCop class KegOnly < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
keg_only_node = find_node_method_by_name(body_node, :keg_only) keg_only_node = find_node_method_by_name(body_node, :keg_only)
return unless keg_only_node return unless keg_only_node
@ -33,12 +35,17 @@ module RuboCop
first_word = reason.split.first first_word = reason.split.first
if reason =~ /\A[A-Z]/ && !reason.start_with?(*allowlist) if reason =~ /\A[A-Z]/ && !reason.start_with?(*allowlist)
problem "'#{first_word}' from the `keg_only` reason should be '#{first_word.downcase}'." problem "'#{first_word}' from the `keg_only` reason should be '#{first_word.downcase}'." do |corrector|
reason[0] = reason[0].downcase
corrector.replace(@offensive_node.source_range, "\"#{reason}\"")
end
end end
return unless reason.end_with?(".") return unless reason.end_with?(".")
problem "`keg_only` reason should not end with a period." problem "`keg_only` reason should not end with a period." do |corrector|
corrector.replace(@offensive_node.source_range, "\"#{reason.chop}\"")
end
end end
def autocorrect(node) def autocorrect(node)

View File

@ -197,20 +197,17 @@ module RuboCop
# #
# @api private # @api private
class MpiCheck < FormulaCop class MpiCheck < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
# Enforce use of OpenMPI for MPI dependency in core # Enforce use of OpenMPI for MPI dependency in core
return unless formula_tap == "homebrew-core" return unless formula_tap == "homebrew-core"
find_method_with_args(body_node, :depends_on, "mpich") do find_method_with_args(body_node, :depends_on, "mpich") do
problem "Formulae in homebrew/core should use 'depends_on \"open-mpi\"' " \ problem "Formulae in homebrew/core should use 'depends_on \"open-mpi\"' " \
"instead of '#{@offensive_node.source}'." "instead of '#{@offensive_node.source}'." do |corrector|
end corrector.replace(@offensive_node.source_range, "depends_on \"open-mpi\"")
end end
def autocorrect(node)
# The dependency nodes may need to be re-sorted because of this
lambda do |corrector|
corrector.replace(node.source_range, "depends_on \"open-mpi\"")
end end
end end
end end
@ -219,6 +216,8 @@ module RuboCop
# #
# @api private # @api private
class SafePopenCommands < FormulaCop class SafePopenCommands < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
test = find_block(body_node, :test) test = find_block(body_node, :test)
@ -233,23 +232,21 @@ module RuboCop
find_instance_method_call(body_node, "Utils", unsafe_command) do |method| find_instance_method_call(body_node, "Utils", unsafe_command) do |method|
unless test_methods.include?(method.source_range) unless test_methods.include?(method.source_range)
problem "Use `Utils.safe_#{unsafe_command}` instead of `Utils.#{unsafe_command}`" problem "Use `Utils.safe_#{unsafe_command}` instead of `Utils.#{unsafe_command}`" do |corrector|
corrector.replace(@offensive_node.loc.selector, "safe_#{@offensive_node.method_name}")
end
end end
end end
end end
end end
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.loc.selector, "safe_#{node.method_name}")
end
end
end end
# This cop makes sure that environment variables are passed correctly to `popen_*` calls. # This cop makes sure that environment variables are passed correctly to `popen_*` calls.
# #
# @api private # @api private
class ShellVariables < FormulaCop class ShellVariables < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
popen_commands = [ popen_commands = [
:popen, :popen,
@ -265,23 +262,21 @@ module RuboCop
good_args = "Utils.#{command}({ \"#{match[1]}\" => \"#{match[2]}\" }, \"#{match[3]}\")" good_args = "Utils.#{command}({ \"#{match[1]}\" => \"#{match[2]}\" }, \"#{match[3]}\")"
problem "Use `#{good_args}` instead of `#{method.source}`" problem "Use `#{good_args}` instead of `#{method.source}`" do |corrector|
corrector.replace(@offensive_node.source_range,
"{ \"#{match[1]}\" => \"#{match[2]}\" }, \"#{match[3]}\"")
end
end end
end end
end end
def autocorrect(node)
lambda do |corrector|
match = regex_match_group(node, /^([^"' ]+)=([^"' ]+)(?: (.*))?$/)
corrector.replace(node.source_range, "{ \"#{match[1]}\" => \"#{match[2]}\" }, \"#{match[3]}\"")
end
end
end end
# This cop makes sure that `license` has the correct format. # This cop makes sure that `license` has the correct format.
# #
# @api private # @api private
class LicenseArrays < FormulaCop class LicenseArrays < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
license_node = find_node_method_by_name(body_node, :license) license_node = find_node_method_by_name(body_node, :license)
return unless license_node return unless license_node
@ -289,12 +284,8 @@ module RuboCop
license = parameters(license_node).first license = parameters(license_node).first
return unless license.array_type? return unless license.array_type?
problem "Use `license any_of: #{license.source}` instead of `license #{license.source}`" problem "Use `license any_of: #{license.source}` instead of `license #{license.source}`" do |corrector|
end corrector.replace(license_node.source_range, "license any_of: #{parameters(license_node).first.source}")
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, "license any_of: #{parameters(node).first.source}")
end end
end end
end end
@ -324,6 +315,8 @@ module RuboCop
# #
# @api private # @api private
class PythonVersions < FormulaCop class PythonVersions < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
python_formula_node = find_every_method_call_by_name(body_node, :depends_on).find do |dep| python_formula_node = find_every_method_call_by_name(body_node, :depends_on).find do |dep|
string_content(parameters(dep).first).start_with? "python@" string_content(parameters(dep).first).start_with? "python@"
@ -334,25 +327,22 @@ module RuboCop
python_version = string_content(parameters(python_formula_node).first).split("@").last python_version = string_content(parameters(python_formula_node).first).split("@").last
find_strings(body_node).each do |str| find_strings(body_node).each do |str|
string_content = string_content(str) content = string_content(str)
next unless match = string_content.match(/^python(@)?(\d\.\d+)$/) next unless match = content.match(/^python(@)?(\d\.\d+)$/)
next if python_version == match[2] next if python_version == match[2]
@fix = if match[1] fix = if match[1]
"python@#{python_version}" "python@#{python_version}"
else else
"python#{python_version}" "python#{python_version}"
end end
offending_node(str) offending_node(str)
problem "References to `#{string_content}` should match the specified python dependency (`#{@fix}`)" problem "References to `#{content}` should "\
end "match the specified python dependency (`#{fix}`)" do |corrector|
end corrector.replace(str.source_range, "\"#{fix}\"")
end
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, "\"#{@fix}\"")
end end
end end
end end
@ -534,7 +524,7 @@ module RuboCop
"Pass explicit paths to prevent Homebrew from removing empty folders." "Pass explicit paths to prevent Homebrew from removing empty folders."
end end
if find_method_def(@processed_source.ast) if find_method_def(processed_source.ast)
problem "Define method #{method_name(@offensive_node)} in the class body, not at the top-level" problem "Define method #{method_name(@offensive_node)} in the class body, not at the top-level"
end end
@ -661,6 +651,8 @@ module RuboCop
# #
# @api private # @api private
class ShellCommands < FormulaCop class ShellCommands < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
# Match shell commands separated by spaces in the same string # Match shell commands separated by spaces in the same string
shell_cmd_with_spaces_regex = /[^"' ]*(?:\s[^"' ]*)+/ shell_cmd_with_spaces_regex = /[^"' ]*(?:\s[^"' ]*)+/
@ -682,7 +674,9 @@ module RuboCop
good_args = match[0].gsub(" ", "\", \"") good_args = match[0].gsub(" ", "\", \"")
offending_node(parameters(method).first) offending_node(parameters(method).first)
problem "Separate `system` commands into `\"#{good_args}\"`" problem "Separate `system` commands into `\"#{good_args}\"`" do |corrector|
corrector.replace(@offensive_node.source_range, @offensive_node.source.gsub(" ", "\", \""))
end
end end
popen_commands.each do |command| popen_commands.each do |command|
@ -696,17 +690,13 @@ module RuboCop
good_args = match[0].gsub(" ", "\", \"") good_args = match[0].gsub(" ", "\", \"")
offending_node(parameters(method)[index]) offending_node(parameters(method)[index])
problem "Separate `Utils.#{command}` commands into `\"#{good_args}\"`" problem "Separate `Utils.#{command}` commands into `\"#{good_args}\"`" do |corrector|
good_args = @offensive_node.source.gsub(" ", "\", \"")
corrector.replace(@offensive_node.source_range, good_args)
end
end end
end end
end end
def autocorrect(node)
lambda do |corrector|
good_args = node.source.gsub(" ", "\", \"")
corrector.replace(node.source_range, good_args)
end
end
end end
end end
end end

View File

@ -11,6 +11,8 @@ module RuboCop
# #
# @api private # @api private
class LivecheckSkip < FormulaCop class LivecheckSkip < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck) livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank? return if livecheck_node.blank?
@ -21,16 +23,12 @@ module RuboCop
return if find_every_method_call_by_name(livecheck_node).length < 3 return if find_every_method_call_by_name(livecheck_node).length < 3
offending_node(livecheck_node) offending_node(livecheck_node)
problem "Skipped formulae must not contain other livecheck information." problem "Skipped formulae must not contain other livecheck information." do |corrector|
end skip = find_every_method_call_by_name(livecheck_node, :skip).first
def autocorrect(node)
lambda do |corrector|
skip = find_every_method_call_by_name(node, :skip).first
skip = find_strings(skip).first skip = find_strings(skip).first
skip = string_content(skip) if skip.present? skip = string_content(skip) if skip.present?
corrector.replace( corrector.replace(
node.source_range, livecheck_node.source_range,
<<~EOS.strip, <<~EOS.strip,
livecheck do livecheck do
skip#{" \"#{skip}\"" if skip.present?} skip#{" \"#{skip}\"" if skip.present?}
@ -65,7 +63,7 @@ module RuboCop
# #
# @api private # @api private
class LivecheckUrlSymbol < FormulaCop class LivecheckUrlSymbol < FormulaCop
@offense = nil extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck) livecheck_node = find_block(body_node, :livecheck)
@ -110,24 +108,20 @@ module RuboCop
next if url != livecheck_url && url != "#{livecheck_url}/" && "#{url}/" != livecheck_url next if url != livecheck_url && url != "#{livecheck_url}/" && "#{url}/" != livecheck_url
offending_node(livecheck_url_node) offending_node(livecheck_url_node)
@offense = symbol problem "Use `url :#{symbol}`" do |corrector|
problem "Use `url :#{symbol}`" corrector.replace(livecheck_url_node.source_range, "url :#{symbol}")
end
break break
end end
end end
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, "url :#{@offense}")
@offense = nil
end
end
end end
# This cop ensures that the `regex` call in the `livecheck` block uses parentheses. # This cop ensures that the `regex` call in the `livecheck` block uses parentheses.
# #
# @api private # @api private
class LivecheckRegexParentheses < FormulaCop class LivecheckRegexParentheses < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck) livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank? return if livecheck_node.blank?
@ -141,13 +135,9 @@ module RuboCop
return if parentheses?(livecheck_regex_node) return if parentheses?(livecheck_regex_node)
offending_node(livecheck_regex_node) offending_node(livecheck_regex_node)
problem "The `regex` call should always use parentheses." problem "The `regex` call should always use parentheses." do |corrector|
end pattern = livecheck_regex_node.source.split[1..].join
corrector.replace(livecheck_regex_node.source_range, "regex(#{pattern})")
def autocorrect(node)
lambda do |corrector|
pattern = node.source.split[1..].join
corrector.replace(node.source_range, "regex(#{pattern})")
end end
end end
end end
@ -157,6 +147,8 @@ module RuboCop
# #
# @api private # @api private
class LivecheckRegexExtension < FormulaCop class LivecheckRegexExtension < FormulaCop
extend AutoCorrector
TAR_PATTERN = /\\?\.t(ar|(g|l|x)z$|[bz2]{2,4}$)(\\?\.((g|l|x)z)|[bz2]{2,4}|Z)?$/i.freeze TAR_PATTERN = /\\?\.t(ar|(g|l|x)z$|[bz2]{2,4}$)(\\?\.((g|l|x)z)|[bz2]{2,4}|Z)?$/i.freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
@ -175,12 +167,8 @@ module RuboCop
return if match.blank? return if match.blank?
offending_node(regex_node) offending_node(regex_node)
problem "Use `\\.t` instead of `#{match}`" problem "Use `\\.t` instead of `#{match}`" do |corrector|
end node = find_strings(regex_node).first
def autocorrect(node)
lambda do |corrector|
node = find_strings(node).first
correct = node.source.gsub(TAR_PATTERN, "\\.t") correct = node.source.gsub(TAR_PATTERN, "\\.t")
corrector.replace(node.source_range, correct) corrector.replace(node.source_range, correct)
end end
@ -218,6 +206,10 @@ module RuboCop
# #
# @api private # @api private
class LivecheckRegexCaseInsensitive < FormulaCop class LivecheckRegexCaseInsensitive < FormulaCop
extend AutoCorrector
MSG = "Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching."
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if tap_style_exception? :regex_case_sensitive_allowlist return if tap_style_exception? :regex_case_sensitive_allowlist
@ -235,12 +227,8 @@ module RuboCop
return if options_node.source.include?("i") return if options_node.source.include?("i")
offending_node(regex_node) offending_node(regex_node)
problem "Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching." problem MSG do |corrector|
end node = regex_node.regopt
def autocorrect(node)
lambda do |corrector|
node = node.regopt
corrector.replace(node.source_range, "i#{node.source}".chars.sort.join) corrector.replace(node.source_range, "i#{node.source}".chars.sort.join)
end end
end end

View File

@ -8,6 +8,7 @@ module RuboCop
module Cop module Cop
module FormulaAudit module FormulaAudit
# This cop audits `patch`es in formulae. # This cop audits `patch`es in formulae.
# TODO: Many of these could be auto-corrected.
class Patches < FormulaCop class Patches < FormulaCop
extend T::Sig extend T::Sig
@ -26,7 +27,7 @@ module RuboCop
if inline_patches.empty? && patch_end? if inline_patches.empty? && patch_end?
offending_patch_end_node(node) offending_patch_end_node(node)
problem "patch is missing 'DATA'" add_offense(@offense_source_range, message: "patch is missing 'DATA'")
end end
patches_node = find_method_def(body, :patches) patches_node = find_method_def(body, :patches)

View File

@ -27,7 +27,6 @@ module RuboCop
end end
@offensive_node = desc_call @offensive_node = desc_call
@offense_source_range = desc_call.source_range
desc = desc_call.first_argument desc = desc_call.first_argument
@ -39,39 +38,41 @@ module RuboCop
end end
# Check the desc for leading whitespace. # Check the desc for leading whitespace.
problem "Description shouldn't have leading spaces." if regex_match_group(desc, /^\s+/) desc_problem "Description shouldn't have leading spaces." if regex_match_group(desc, /^\s+/)
# Check the desc for trailing whitespace. # Check the desc for trailing whitespace.
problem "Description shouldn't have trailing spaces." if regex_match_group(desc, /\s+$/) desc_problem "Description shouldn't have trailing spaces." if regex_match_group(desc, /\s+$/)
# Check if "command-line" is spelled incorrectly in the desc. # Check if "command-line" is spelled incorrectly in the desc.
if match = regex_match_group(desc, /(command ?line)/i) if match = regex_match_group(desc, /(command ?line)/i)
c = match.to_s[0] c = match.to_s[0]
problem "Description should use \"#{c}ommand-line\" instead of \"#{match}\"." desc_problem "Description should use \"#{c}ommand-line\" instead of \"#{match}\"."
end end
# Check if the desc starts with an article. # Check if the desc starts with an article.
problem "Description shouldn't start with an article." if regex_match_group(desc, /^(the|an?)(?=\s)/i) desc_problem "Description shouldn't start with an article." if regex_match_group(desc, /^(the|an?)(?=\s)/i)
# Check if invalid lowercase words are at the start of a desc. # Check if invalid lowercase words are at the start of a desc.
if !VALID_LOWERCASE_WORDS.include?(string_content(desc).split.first) && if !VALID_LOWERCASE_WORDS.include?(string_content(desc).split.first) &&
regex_match_group(desc, /^[a-z]/) regex_match_group(desc, /^[a-z]/)
problem "Description should start with a capital letter." desc_problem "Description should start with a capital letter."
end end
# Check if the desc starts with the formula's or cask's name. # Check if the desc starts with the formula's or cask's name.
name_regex = name.delete("-").split("").join('[\s\-]?') name_regex = name.delete("-").split("").join('[\s\-]?')
problem "Description shouldn't start with the #{type} name." if regex_match_group(desc, /^#{name_regex}\b/i) if regex_match_group(desc, /^#{name_regex}\b/i)
desc_problem "Description shouldn't start with the #{type} name."
end
if type == :cask && if type == :cask &&
(match = regex_match_group(desc, /\b(macOS|Mac( ?OS( ?X)?)?|OS ?X)(?! virtual machines?)\b/i)) && (match = regex_match_group(desc, /\b(macOS|Mac( ?OS( ?X)?)?|OS ?X)(?! virtual machines?)\b/i)) &&
match[1] != "MAC" match[1] != "MAC"
problem "Description shouldn't contain the platform." desc_problem "Description shouldn't contain the platform."
end end
# Check if a full stop is used at the end of a desc (apart from in the case of "etc."). # Check if a full stop is used at the end of a desc (apart from in the case of "etc.").
if regex_match_group(desc, /\.$/) && !string_content(desc).end_with?("etc.") if regex_match_group(desc, /\.$/) && !string_content(desc).end_with?("etc.")
problem "Description shouldn't end with a full stop." desc_problem "Description shouldn't end with a full stop."
end end
# Check if the desc length exceeds maximum length. # Check if the desc length exceeds maximum length.
@ -81,9 +82,10 @@ module RuboCop
"The current length is #{desc_length}." "The current length is #{desc_length}."
end end
def autocorrect_desc(node, name) # Auto correct desc problems. `regex_match_group` must be called before this to populate @offense_source_range.
lambda do |corrector| def desc_problem(message)
/\A(?<quote>["'])(?<correction>.*)(?:\k<quote>)\Z/ =~ node.source add_offense(@offensive_source_range, message: message) do |corrector|
/\A(?<quote>["'])(?<correction>.*)(?:\k<quote>)\Z/ =~ @offensive_node.source
next if correction.nil? next if correction.nil?
@ -99,12 +101,12 @@ module RuboCop
end end
correction.gsub!(/(ommand ?line)/i, "ommand-line") correction.gsub!(/(ommand ?line)/i, "ommand-line")
correction.gsub!(/(^|[^a-z])#{name}([^a-z]|$)/i, "\\1\\2") correction.gsub!(/(^|[^a-z])#{@name}([^a-z]|$)/i, "\\1\\2")
correction.gsub!(/^\s+/, "") correction.gsub!(/^\s+/, "")
correction.gsub!(/\s+$/, "") correction.gsub!(/\s+$/, "")
correction.gsub!(/\.$/, "") correction.gsub!(/\.$/, "")
corrector.replace(node.source_range, "#{quote}#{correction}#{quote}") corrector.replace(@offensive_node.source_range, "#{quote}#{correction}#{quote}")
end end
end end
end end

View File

@ -28,8 +28,8 @@ module RuboCop
@length = match_object.to_s.length @length = match_object.to_s.length
@line_no = line_number(node) @line_no = line_number(node)
@source_buf = source_buffer(node) @source_buf = source_buffer(node)
@offense_source_range = source_range(@source_buf, @line_no, @column, @length)
@offensive_node = node @offensive_node = node
@offensive_source_range = source_range(@source_buf, @line_no, @column, @length)
match_object match_object
end end
@ -77,8 +77,8 @@ module RuboCop
end end
end end
def problem(msg) def problem(msg, &block)
add_offense(@offensive_node, location: @offense_source_range, message: msg) add_offense(@offensive_node, message: msg, &block)
end end
end end
end end

View File

@ -10,17 +10,16 @@ module RuboCop
# #
# @api private # @api private
class Text < FormulaCop class Text < FormulaCop
def audit_formula(node, _class_node, _parent_class_node, body_node) extend AutoCorrector
@full_source_content = source_buffer(node).source
if match = @full_source_content.match(/^require ['"]formula['"]$/) def audit_formula(node, _class_node, _parent_class_node, body_node)
@offensive_node = node full_source_content = source_buffer(node).source
@source_buf = source_buffer(node)
@line_no = match.pre_match.count("\n") + 1 if match = full_source_content.match(/^require ['"]formula['"]$/)
@column = 0 range = source_range(source_buffer(node), match.pre_match.count("\n") + 1, 0, match[0].length)
@length = match[0].length add_offense(range, message: "`#{match}` is now unnecessary") do |corrector|
@offense_source_range = source_range(@source_buf, @line_no, @column, @length) corrector.remove(range_with_surrounding_space(range: range))
problem "`#{match}` is now unnecessary" end
end end
if !find_node_method_by_name(body_node, :plist_options) && if !find_node_method_by_name(body_node, :plist_options) &&

View File

@ -7,8 +7,9 @@ module RuboCop
# This cop checks that `unless` is not used with multiple conditions. # This cop checks that `unless` is not used with multiple conditions.
# #
# @api private # @api private
class UnlessMultipleConditions < Cop class UnlessMultipleConditions < Base
extend T::Sig extend T::Sig
extend AutoCorrector
MSG = "Avoid using `unless` with multiple conditions." MSG = "Avoid using `unless` with multiple conditions."
@ -16,12 +17,7 @@ module RuboCop
def on_if(node) def on_if(node)
return if !node.unless? || (!node.condition.and_type? && !node.condition.or_type?) return if !node.unless? || (!node.condition.and_type? && !node.condition.or_type?)
add_offense(node, location: node.condition.source_range.with(begin_pos: node.loc.keyword.begin_pos)) add_offense(node.condition.source_range.with(begin_pos: node.loc.keyword.begin_pos)) do |corrector|
end
sig { params(node: RuboCop::AST::IfNode).returns(T.proc.params(arg0: RuboCop::Cop::Corrector).void) }
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.loc.keyword, "if") corrector.replace(node.loc.keyword, "if")
corrector.replace(node.condition.loc.operator, node.condition.inverse_operator) corrector.replace(node.condition.loc.operator, node.condition.inverse_operator)
[node.condition.lhs, node.condition.rhs].each do |subcondition| [node.condition.lhs, node.condition.rhs].each do |subcondition|

View File

@ -21,14 +21,13 @@ module CaskCop
end end
def expect_no_offenses(source) def expect_no_offenses(source)
inspect_source(source) expect(inspect_source(source)).to be_empty
expect(cop.offenses).to be_empty
end end
def expect_reported_offenses(source, expected_offenses) def expect_reported_offenses(source, expected_offenses)
inspect_source(source) offenses = inspect_source(source)
expect(cop.offenses.size).to eq(expected_offenses.size) expect(offenses.size).to eq(expected_offenses.size)
expected_offenses.zip(cop.offenses).each do |expected, actual| expected_offenses.zip(offenses).each do |expected, actual|
expect_offense(expected, actual) expect_offense(expected, actual)
end end
end end

View File

@ -14,7 +14,7 @@ describe RuboCop::Cop::FormulaAudit::Caveats do
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
def caveats def caveats
"setuid" "setuid"
^^^^^^ Don\'t recommend setuid in the caveats, suggest sudo instead. ^^^^^^^^ Don\'t recommend setuid in the caveats, suggest sudo instead.
end end
end end
RUBY RUBY

View File

@ -33,12 +33,12 @@ describe RuboCop::Cop::FormulaAudit::Checksum do
stable do stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c0474cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9ad" sha256 "5cf6e1ae0a645b426c0474cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9ad"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sha256 should be 64 characters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sha256 should be 64 characters
resource "foo-package" do resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz" url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c047aaa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9" sha256 "5cf6e1ae0a645b426c047aaa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sha256 should be 64 characters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sha256 should be 64 characters
end end
end end
end end
@ -89,7 +89,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do
RUBY RUBY
end end
it "reports an offense if a checksum outside a `stable` block contains uppercase letters" do it "reports and corrects an offense if a checksum outside a `stable` block contains uppercase letters" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -109,27 +109,14 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do
end end
end end
RUBY RUBY
end
it "auto-corrects checksums that contain uppercase letters" do expect_correction(<<~RUBY)
source = <<~RUBY
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
stable do resource "foo-outside" do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" url "https://github.com/foo-lang/foo-outside/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0A645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a" sha256 "a4cc7cd3f7d1605ffa1ac5755cf6e1ae0a645b426b047a6a39a8b2268ddc7ea9"
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1Ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
end
end end
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
stable do stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a" sha256 "5cf6e1ae0a645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
@ -141,9 +128,6 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do
end end
end end
RUBY RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end end
end end
end end

View File

@ -6,55 +6,47 @@ require "rubocops/class"
describe RuboCop::Cop::FormulaAudit::ClassName do describe RuboCop::Cop::FormulaAudit::ClassName do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
it "reports an offense when using ScriptFileFormula" do corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
it "reports and corrects an offense when using ScriptFileFormula" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < ScriptFileFormula class Foo < ScriptFileFormula
^^^^^^^^^^^^^^^^^ ScriptFileFormula is deprecated, use Formula instead ^^^^^^^^^^^^^^^^^ ScriptFileFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
end end
RUBY RUBY
expect_correction(corrected_source)
end end
it "reports an offense when using GithubGistFormula" do it "reports and corrects an offense when using GithubGistFormula" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < GithubGistFormula class Foo < GithubGistFormula
^^^^^^^^^^^^^^^^^ GithubGistFormula is deprecated, use Formula instead ^^^^^^^^^^^^^^^^^ GithubGistFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
end end
RUBY RUBY
expect_correction(corrected_source)
end end
it "reports an offense when using AmazonWebServicesFormula" do it "reports and corrects an offense when using AmazonWebServicesFormula" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < AmazonWebServicesFormula class Foo < AmazonWebServicesFormula
^^^^^^^^^^^^^^^^^^^^^^^^ AmazonWebServicesFormula is deprecated, use Formula instead ^^^^^^^^^^^^^^^^^^^^^^^^ AmazonWebServicesFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
end end
RUBY RUBY
end expect_correction(corrected_source)
it "supports auto-correcting deprecated parent classes" do
source = <<~RUBY
class Foo < AmazonWebServicesFormula
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end end
end end
describe RuboCop::Cop::FormulaAudit::Test do describe RuboCop::Cop::FormulaAudit::Test do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
it "reports an offense when /usr/local/bin is found in test calls" do it "reports and corrects an offense when /usr/local/bin is found in test calls" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -65,9 +57,19 @@ describe RuboCop::Cop::FormulaAudit::Test do
end end
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
system "\#{bin}/test"
end
end
RUBY
end end
it "reports an offense when passing 0 as the second parameter to shell_output" do it "reports and corrects an offense when passing 0 as the second parameter to shell_output" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -78,6 +80,16 @@ describe RuboCop::Cop::FormulaAudit::Test do
end end
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
shell_output("\#{bin}/test")
end
end
RUBY
end end
it "reports an offense when there is an empty test block" do it "reports an offense when there is an empty test block" do
@ -104,31 +116,6 @@ describe RuboCop::Cop::FormulaAudit::Test do
end end
RUBY RUBY
end end
it "supports auto-correcting test calls" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
shell_output("/usr/local/sbin/test", 0)
end
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
test do
shell_output("\#{sbin}/test")
end
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end end
describe RuboCop::Cop::FormulaAuditStrict::TestPresent do describe RuboCop::Cop::FormulaAuditStrict::TestPresent do

View File

@ -7,7 +7,7 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula components order" do context "When auditing formula components order" do
it "When uses_from_macos precedes depends_on" do it "reports and corrects an offense when `uses_from_macos` precedes `depends_on`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -18,9 +18,20 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^ `depends_on` (line 6) should be put before `uses_from_macos` (line 5) ^^^^^^^^^^^^^^^^ `depends_on` (line 6) should be put before `uses_from_macos` (line 5)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
depends_on "foo"
uses_from_macos "apple"
end
RUBY
end end
it "When license precedes sha256" do it "reports and corrects an offense when `license` precedes `sha256`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -30,9 +41,18 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^^ `sha256` (line 5) should be put before `license` (line 4) ^^^^^^^^^^^^^^^^^^^^^ `sha256` (line 5) should be put before `license` (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
sha256 "samplesha256"
license "0BSD"
end
RUBY
end end
it "When `bottle` precedes `livecheck`" do it "reports and corrects an offense when `bottle` precedes `livecheck`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -47,9 +67,23 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
end end
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo/versions/"
regex(/href=.+?foo-(\d+(?:\.\d+)+)\.t/)
end
bottle :unneeded
end
RUBY
end end
it "When url precedes homepage" do it "reports and corrects an offense when `url` precedes `homepage`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -57,9 +91,16 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^^^^^^^ `homepage` (line 3) should be put before `url` (line 2) ^^^^^^^^^^^^^^^^^^^^^^^^^^ `homepage` (line 3) should be put before `url` (line 2)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
end end
it "When `resource` precedes `depends_on`" do it "reports and corrects an offense when `resource` precedes `depends_on`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -72,9 +113,21 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 8) should be put before `resource` (line 4) ^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 8) should be put before `resource` (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
depends_on "openssl"
resource "foo2" do
url "https://brew.sh/foo-2.0.tgz"
end
end
RUBY
end end
it "When `test` precedes `plist`" do it "reports and corrects an offense when `test` precedes `plist`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -88,9 +141,22 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
end end
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
def plist
end
test do
expect(shell_output("./dogs")).to match("Dogs are terrific")
end
end
RUBY
end end
it "When `install` precedes `depends_on`" do it "reports and corrects an offense when `install` precedes `depends_on`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -102,9 +168,20 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 7) should be put before `install` (line 4) ^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 7) should be put before `install` (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
depends_on "openssl"
def install
end
end
RUBY
end end
it "When `test` precedes `depends_on`" do it "reports and corrects an offense when `test` precedes `depends_on`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -119,9 +196,23 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 10) should be put before `install` (line 4) ^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 10) should be put before `install` (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
depends_on "openssl"
def install
end
def test
end
end
RUBY
end end
it "When only one of many `depends_on` precedes `conflicts_with`" do it "reports and corrects an offense when only one of many `depends_on` precedes `conflicts_with`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
depends_on "autoconf" => :build depends_on "autoconf" => :build
@ -133,9 +224,20 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
depends_on "gettext" depends_on "gettext"
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
depends_on "autoconf" => :build
depends_on "automake" => :build
depends_on "libtool" => :build
depends_on "pkg-config" => :build
depends_on "gettext"
conflicts_with "visionmedia-watch"
end
RUBY
end end
it "the on_macos block is not after uses_from_macos" do it "reports and corrects an offense when the `on_macos` block precedes `uses_from_macos`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -146,9 +248,20 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` (line 6) should be put before `on_macos` (line 3) ^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` (line 6) should be put before `on_macos` (line 3)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "bar"
on_macos do
depends_on "readline"
end
end
RUBY
end end
it "the on_linux block is not after uses_from_macos" do it "reports and corrects an offense when the `on_linux` block precedes `uses_from_macos`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -159,9 +272,20 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` (line 6) should be put before `on_linux` (line 3) ^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` (line 6) should be put before `on_linux` (line 3)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "bar"
on_linux do
depends_on "readline"
end
end
RUBY
end end
it "the on_linux block is not after the on_macos block" do it "reports and corrects an offense when the `on_linux` block precedes the `on_macos` block" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -174,82 +298,43 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
end end
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
on_macos do
depends_on "readline"
end
on_linux do
depends_on "vim"
end
end
RUBY
end end
end end
context "When auditing formula components order with autocorrect" do it "reports and corrects an offense when `depends_on` precedes `deprecate!`" do
it "When url precedes homepage" do expect_offense(<<~RUBY)
source = <<~RUBY class Foo < Formula
class Foo < Formula url "https://brew.sh/foo-1.0.tgz"
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
end
RUBY
correct_source = <<~RUBY depends_on "openssl"
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
corrected_source = autocorrect_source(source) deprecate! because: "has been replaced by bar"
expect(corrected_source).to eq(correct_source) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `deprecate!` (line 6) should be put before `depends_on` (line 4)
end end
RUBY
it "When `resource` precedes `depends_on`" do expect_correction(<<~RUBY)
source = <<~RUBY class Foo < Formula
class Foo < Formula url "https://brew.sh/foo-1.0.tgz"
url "https://brew.sh/foo-1.0.tgz"
resource "foo2" do deprecate! because: "has been replaced by bar"
url "https://brew.sh/foo-2.0.tgz"
end
depends_on "openssl" depends_on "openssl"
end end
RUBY RUBY
correct_source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
depends_on "openssl"
resource "foo2" do
url "https://brew.sh/foo-2.0.tgz"
end
end
RUBY
corrected_source = autocorrect_source(source)
expect(corrected_source).to eq(correct_source)
end
it "When `depends_on` precedes `deprecate!`" do
source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
depends_on "openssl"
deprecate! because: "has been replaced by bar"
end
RUBY
correct_source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
deprecate! because: "has been replaced by bar"
depends_on "openssl"
end
RUBY
corrected_source = autocorrect_source(source)
expect(corrected_source).to eq(correct_source)
end
end end
context "no on_os_block" do context "no on_os_block" do
@ -351,321 +436,321 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
end end
RUBY RUBY
end end
end
it "there can only be one on_macos block" do it "reports an offense when there are multiple `on_macos` blocks" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
on_macos do
depends_on "readline"
end
on_macos do
^^^^^^^^^^^ there can only be one `on_macos` block in a formula.
depends_on "foo"
end
end
RUBY
end
it "there can only be one on_linux block" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
on_linux do
depends_on "readline"
end
on_linux do
^^^^^^^^^^^ there can only be one `on_linux` block in a formula.
depends_on "foo"
end
end
RUBY
end
it "the on_macos block can only contain depends_on, patch and resource nodes" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
on_macos do
depends_on "readline"
uses_from_macos "ncurses"
^^^^^^^^^^^^^^^^^^^^^^^^^ `on_macos` cannot include `uses_from_macos`. [...]
end
end
RUBY
end
it "the on_linux block can only contain depends_on, patch and resource nodes" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
on_linux do
depends_on "readline"
uses_from_macos "ncurses"
^^^^^^^^^^^^^^^^^^^^^^^^^ `on_linux` cannot include `uses_from_macos`. [...]
end
end
RUBY
end
context "in a resource block" do
it "reports no offenses for a valid on_macos and on_linux block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
resource do
on_macos do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports no offenses for a valid on_macos and on_linux block with versions" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
resource do
on_macos do
url "https://brew.sh/resource1.tar.gz"
version "1.2.3"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
version "1.2.3"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if there are two on_macos blocks" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
on_macos do
depends_on "readline"
end
resource do on_macos do
^^^^^^^^^^^ there can only be one `on_macos` block in a resource block. ^^^^^^^^^^^ there can only be one `on_macos` block in a formula.
on_macos do depends_on "foo"
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end end
end end
RUBY RUBY
end end
it "reports an offense if there are two on_linux blocks" do it "reports an offense when there are multiple `on_linux` blocks" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
on_linux do
depends_on "readline"
end
resource do on_linux do
^^^^^^^^^^^ there can only be one `on_linux` block in a resource block. ^^^^^^^^^^^ there can only be one `on_linux` block in a formula.
on_linux do depends_on "foo"
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end end
end end
RUBY RUBY
end end
it "reports no offenses if there is an on_macos block but no on_linux block" do it "reports an offense when the `on_macos` block contains nodes other than `depends_on`, `patch` or `resource`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_macos do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports no offenses if there is an on_linux block but no on_macos block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_linux do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if the content of an on_macos block is improperly formatted" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
on_macos do
resource do depends_on "readline"
^^^^^^^^^^^ `on_macos` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders). uses_from_macos "ncurses"
on_macos do ^^^^^^^^^^^^^^^^^^^^^^^^^ `on_macos` cannot include `uses_from_macos`. [...]
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource2.tar.gz"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end end
end end
RUBY RUBY
end end
it "reports no offenses if an on_macos block has if-else branches that are properly formatted" do it "reports an offense when the `on_linux` block contains nodes other than `depends_on`, `patch` or `resource`" do
expect_no_offenses(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
on_linux do
depends_on "readline"
uses_from_macos "ncurses"
^^^^^^^^^^^^^^^^^^^^^^^^^ `on_linux` cannot include `uses_from_macos`. [...]
end
end
RUBY
end
resource do context "in a resource block" do
on_macos do it "reports no offenses for a valid `on_macos` and `on_linux` block" do
if foo == :bar expect_no_offenses(<<~RUBY)
url "https://brew.sh/resource2.tar.gz" class Foo < Formula
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" homepage "https://brew.sh"
else
resource do
on_macos do
url "https://brew.sh/resource1.tar.gz" url "https://brew.sh/resource1.tar.gz"
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end end
end
on_linux do on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if an on_macos block has if-else branches that aren't properly formatted" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ `on_macos` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders).
on_macos do
if foo == :bar
url "https://brew.sh/resource2.tar.gz" url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource1.tar.gz"
end
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if the content of an on_linux block is improperly formatted" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ `on_linux` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders).
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource2.tar.gz"
end
end
end
RUBY
end
it "reports no offenses if an on_linux block has if-else branches that are properly formatted" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
if foo == :bar
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
url "https://brew.sh/resource1.tar.gz"
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end end
end end
end end
end RUBY
RUBY end
end
it "reports an offense if an on_linux block has if-else branches that aren't properly formatted" do it "reports no offenses for a valid `on_macos` and `on_linux` block with versions" do
expect_offense(<<~RUBY) expect_no_offenses(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" homepage "https://brew.sh"
resource do resource do
^^^^^^^^^^^ `on_linux` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders). on_macos do
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
if foo == :bar
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource1.tar.gz" url "https://brew.sh/resource1.tar.gz"
version "1.2.3"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
version "1.2.3"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end end
end end
end end
end RUBY
RUBY end
it "reports an offense if there are two `on_macos` blocks" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ there can only be one `on_macos` block in a resource block.
on_macos do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if there are two `on_linux` blocks" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ there can only be one `on_linux` block in a resource block.
on_linux do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports no offenses if there is an `on_macos` block but no `on_linux` block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_macos do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports no offenses if there is an `on_linux` block but no `on_macos` block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_linux do
url "https://brew.sh/resource1.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if the content of an `on_macos` block is improperly formatted" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ `on_macos` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders).
on_macos do
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource2.tar.gz"
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports no offenses if an `on_macos` block has if-else branches that are properly formatted" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_macos do
if foo == :bar
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
url "https://brew.sh/resource1.tar.gz"
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if an `on_macos` block has if-else branches that aren't properly formatted" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ `on_macos` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders).
on_macos do
if foo == :bar
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource1.tar.gz"
end
end
on_linux do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
RUBY
end
it "reports an offense if the content of an `on_linux` block is improperly formatted" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ `on_linux` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders).
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource2.tar.gz"
end
end
end
RUBY
end
it "reports no offenses if an `on_linux` block has if-else branches that are properly formatted" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
if foo == :bar
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
url "https://brew.sh/resource1.tar.gz"
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
end
end
end
RUBY
end
it "reports an offense if an `on_linux` block has if-else branches that aren't properly formatted" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
resource do
^^^^^^^^^^^ `on_linux` blocks within resource blocks must contain only a url and sha256 or a url, version, and sha256 (in those orders).
on_macos do
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
end
on_linux do
if foo == :bar
url "https://brew.sh/resource2.tar.gz"
sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
else
sha256 "686372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"
url "https://brew.sh/resource1.tar.gz"
end
end
end
end
RUBY
end
end end
end end
end end

View File

@ -7,7 +7,7 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "when auditing `conflicts_with`" do context "when auditing `conflicts_with`" do
it "reports an offense if reason is capitalized" do it "reports and corrects an offense if reason is capitalized" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -16,9 +16,17 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
conflicts_with "baz", :because => "Foo is the formula name which does not require downcasing" conflicts_with "baz", :because => "Foo is the formula name which does not require downcasing"
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
conflicts_with "bar", :because => "reason"
conflicts_with "baz", :because => "Foo is the formula name which does not require downcasing"
end
RUBY
end end
it "reports an offense if reason ends with a period" do it "reports and corrects an offense if reason ends with a period" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -26,6 +34,13 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
^^^^^^^^^ `conflicts_with` reason should not end with a period. ^^^^^^^^^ `conflicts_with` reason should not end with a period.
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
conflicts_with "bar", "baz", :because => "reason"
end
RUBY
end end
it "reports an offense if it is present in a versioned formula" do it "reports an offense if it is present in a versioned formula" do
@ -46,43 +61,5 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
end end
RUBY RUBY
end end
it "auto-corrects capitalized reason" do
source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
conflicts_with "bar", :because => "Reason"
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
conflicts_with "bar", :because => "reason"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
it "auto-corrects trailing period" do
source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
conflicts_with "bar", :because => "reason."
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
conflicts_with "bar", :because => "reason"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end end
end end

View File

@ -7,7 +7,7 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "when auditing `uses_from_macos`" do context "when auditing `uses_from_macos`" do
it "reports an offense if wrong conditional order" do it "reports and corrects incorrectly ordered conditional dependencies" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -17,9 +17,18 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 5) should be put before dependency "apple" (line 4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 5) should be put before dependency "apple" (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "foo" => :optional
uses_from_macos "apple" if build.with? "foo"
end
RUBY
end end
it "reports an offense if wrong alphabetical order" do it "reports and corrects incorrectly ordered alphabetical dependencies" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -29,9 +38,18 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "foo" (line 4) ^^^^^^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "foo" (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "bar"
uses_from_macos "foo"
end
RUBY
end end
it "supports requirement constants" do it "reports and corrects incorrectly ordered dependencies that are Requirements" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -41,9 +59,18 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "FooRequirement" (line 4) ^^^^^^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "FooRequirement" (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "bar"
uses_from_macos FooRequirement
end
RUBY
end end
it "reports an offense if wrong conditional order with block" do it "reports and corrects wrong conditional order within a spec block" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -60,6 +87,20 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 10) should be put before dependency "apple" (line 9) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 10) should be put before dependency "apple" (line 9)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
head do
uses_from_macos "bar"
uses_from_macos "foo" => :optional
uses_from_macos "apple" if build.with? "foo"
end
uses_from_macos "foo" => :optional
uses_from_macos "apple" if build.with? "foo"
end
RUBY
end end
it "reports no offenses if correct order for multiple tags" do it "reports no offenses if correct order for multiple tags" do
@ -76,7 +117,7 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
end end
context "when auditing `depends_on`" do context "when auditing `depends_on`" do
it "reports an offense if wrong conditional order" do it "reports and corrects incorrectly ordered conditional dependencies" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -86,9 +127,18 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 5) should be put before dependency "apple" (line 4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 5) should be put before dependency "apple" (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
depends_on "foo" => :optional
depends_on "apple" if build.with? "foo"
end
RUBY
end end
it "reports an offense if wrong alphabetical order" do it "reports and corrects incorrectly ordered alphabetical dependencies" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -98,9 +148,18 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "foo" (line 4) ^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "foo" (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
depends_on "bar"
depends_on "foo"
end
RUBY
end end
it "supports requirement constants" do it "reports and corrects incorrectly ordered dependencies that are Requirements" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -110,9 +169,18 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "FooRequirement" (line 4) ^^^^^^^^^^^^^^^^ dependency "bar" (line 5) should be put before dependency "FooRequirement" (line 4)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
depends_on "bar"
depends_on FooRequirement
end
RUBY
end end
it "reports an offense if wrong conditional order with block" do it "reports and corrects wrong conditional order within a spec block" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "https://brew.sh" homepage "https://brew.sh"
@ -129,6 +197,20 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 10) should be put before dependency "apple" (line 9) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dependency "foo" (line 10) should be put before dependency "apple" (line 9)
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
head do
depends_on "bar"
depends_on "foo" => :optional
depends_on "apple" if build.with? "foo"
end
depends_on "foo" => :optional
depends_on "apple" if build.with? "foo"
end
RUBY
end end
it "reports no offenses if correct order for multiple tags" do it "reports no offenses if correct order for multiple tags" do
@ -143,52 +225,4 @@ describe RuboCop::Cop::FormulaAudit::DependencyOrder do
RUBY RUBY
end end
end end
context "when auto-correcting" do
it "supports wrong conditional `uses_from_macos` order" do
source = <<~RUBY
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "apple" if build.with? "foo"
uses_from_macos "foo" => :optional
end
RUBY
correct_source = <<~RUBY
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
uses_from_macos "foo" => :optional
uses_from_macos "apple" if build.with? "foo"
end
RUBY
corrected_source = autocorrect_source(source)
expect(corrected_source).to eq(correct_source)
end
it "supports wrong conditional `depends_on` order" do
source = <<~RUBY
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
depends_on "apple" if build.with? "foo"
depends_on "foo" => :optional
end
RUBY
correct_source = <<~RUBY
class Foo < Formula
homepage "https://brew.sh"
url "https://brew.sh/foo-1.0.tgz"
depends_on "foo" => :optional
depends_on "apple" if build.with? "foo"
end
RUBY
corrected_source = autocorrect_source(source)
expect(corrected_source).to eq(correct_source)
end
end
end end

View File

@ -7,7 +7,7 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "when auditing `deprecate!`" do context "when auditing `deprecate!`" do
it "reports an offense if `date` is not ISO 8601 compliant" do it "reports and corrects an offense if `date` is not ISO 8601 compliant" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -15,9 +15,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601 ^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-06-25"
end
RUBY
end end
it "reports an offense if `date` is not ISO 8601 compliant (with `reason`)" do it "reports and corrects an offense if `date` is not ISO 8601 compliant (with `reason`)" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -25,6 +32,13 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601 ^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "2020-06-25"
end
RUBY
end end
it "reports no offenses if `date` is ISO 8601 compliant" do it "reports no offenses if `date` is ISO 8601 compliant" do
@ -62,48 +76,10 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
end end
RUBY RUBY
end end
it "auto-corrects `date` to ISO 8601 format" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "June 25, 2020"
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-06-25"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
it "auto-corrects `date` to ISO 8601 format (with `reason`)" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "June 25, 2020"
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "2020-06-25"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end end
context "when auditing `disable!`" do context "when auditing `disable!`" do
it "reports an offense if `date` is not ISO 8601 compliant" do it "reports and corrects an offense if `date` is not ISO 8601 compliant" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -111,9 +87,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601 ^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-06-25"
end
RUBY
end end
it "reports an offense if `date` is not ISO 8601 compliant (with `reason`)" do it "reports and corrects an offense if `date` is not ISO 8601 compliant (with `reason`)" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -121,6 +104,13 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601 ^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "2020-06-25"
end
RUBY
end end
it "reports no offenses if `date` is ISO 8601 compliant" do it "reports no offenses if `date` is ISO 8601 compliant" do
@ -158,44 +148,6 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
end end
RUBY RUBY
end end
it "auto-corrects `date` to ISO 8601 format" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "June 25, 2020"
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-06-25"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
it "auto-corrects `date` to ISO 8601 format (with `reason`)" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "June 25, 2020"
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "2020-06-25"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end end
end end
@ -259,7 +211,7 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
RUBY RUBY
end end
it "reports an offense if `reason` starts with 'it'" do it "reports and corrects an offense if `reason` starts with 'it'" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -267,9 +219,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^^^ Do not start the reason with `it` ^^^^^^^^^^^^^^ Do not start the reason with `it`
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` starts with 'it' (with `date`)" do it "reports and corrects an offense if `reason` starts with 'it' (with `date`)" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -277,9 +236,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^^^ Do not start the reason with `it` ^^^^^^^^^^^^^^ Do not start the reason with `it`
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-08-28", because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with a period" do it "reports and corrects an offense if `reason` ends with a period" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -287,9 +253,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with an exclamation point" do it "reports and corrects an offense if `reason` ends with an exclamation point" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -297,9 +270,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with a question mark" do it "reports and corrects an offense if `reason` ends with a question mark" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -307,9 +287,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with a period (with `date`)" do it "reports and corrects an offense if `reason` ends with a period (with `date`)" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -317,44 +304,13 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
end
it "auto-corrects `reason` to remove 'it'" do expect_correction(<<~RUBY)
source = <<~RUBY
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "it is broken" deprecate! date: "2020-08-28", because: "is broken"
end end
RUBY RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
it "auto-corrects `reason` to remove punctuation" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken."
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end end
end end
@ -415,7 +371,7 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
RUBY RUBY
end end
it "reports an offense if `reason` starts with 'it'" do it "reports and corrects an offense if `reason` starts with 'it'" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -423,9 +379,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^^^ Do not start the reason with `it` ^^^^^^^^^^^^^^ Do not start the reason with `it`
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` starts with 'it' (with `date`)" do it "reports and corrects an offense if `reason` starts with 'it' (with `date`)" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -433,9 +396,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^^^ Do not start the reason with `it` ^^^^^^^^^^^^^^ Do not start the reason with `it`
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-08-28", because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with a period" do it "reports and corrects an offense if `reason` ends with a period" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -443,9 +413,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with an exclamation point" do it "reports and corrects an offense if `reason` ends with an exclamation point" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -453,9 +430,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with a question mark" do it "reports and corrects an offense if `reason` ends with a question mark" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -463,9 +447,16 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
end end
it "reports an offense if `reason` ends with a period (with `date`)" do it "reports and corrects an offense if `reason` ends with a period (with `date`)" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -473,44 +464,13 @@ describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
^^^^^^^^^^^^ Do not end the reason with a punctuation mark ^^^^^^^^^^^^ Do not end the reason with a punctuation mark
end end
RUBY RUBY
end
it "auto-corrects to remove 'it'" do expect_correction(<<~RUBY)
source = <<~RUBY
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
disable! because: "it is broken" disable! date: "2020-08-28", because: "is broken"
end end
RUBY RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
it "auto-corrects to remove punctuation" do
source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken."
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end end
end end
end end

View File

@ -6,8 +6,8 @@ require "rubocops/formula_desc"
describe RuboCop::Cop::FormulaAudit::Desc do describe RuboCop::Cop::FormulaAudit::Desc do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing formula desc" do context "When auditing formula `desc` methods" do
it "When there is no desc" do it "reports an offense when there is no `desc`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
^^^^^^^^^^^^^^^^^^^ Formula should have a desc (Description). ^^^^^^^^^^^^^^^^^^^ Formula should have a desc (Description).
@ -16,7 +16,7 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "When desc is an empty string" do it "reports an offense when `desc` is an empty string" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -26,7 +26,7 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "When desc is too long" do it "reports an offense when `desc` is too long" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -36,7 +36,7 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "When desc is a multiline string" do it "reports an offense when `desc` is a multiline string" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -48,39 +48,39 @@ describe RuboCop::Cop::FormulaAudit::Desc do
end end
end end
context "When auditing formula desc" do context "When auditing formula description texts" do
it "When the description starts with a leading space" do it "reports an offense when the description starts with a leading space" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
desc ' Description with a leading space' desc ' Description with a leading space'
^ Description shouldn\'t have leading spaces. ^ Description shouldn't have leading spaces.
end end
RUBY RUBY
end end
it "When the description ends with a trailing space" do it "reports an offense when the description ends with a trailing space" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
desc 'Description with a trailing space ' desc 'Description with a trailing space '
^ Description shouldn\'t have trailing spaces. ^ Description shouldn't have trailing spaces.
end end
RUBY RUBY
end end
it "When \"command-line\" is incorrectly spelled in the desc" do it "reports an offense when \"command-line\" is incorrectly spelled in the description" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
desc 'command line' desc 'command line'
^ Description should start with a capital letter. ^ Description should start with a capital letter.
^^^^^^^^^^^^ Description should use \"command-line\" instead of \"command line\". ^^^^^^^^^^^^ Description should use "command-line" instead of "command line".
end end
RUBY RUBY
end end
it "When an article is used in the desc" do it "reports an offense when an article is used in the description" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -98,7 +98,7 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "When the desc starts with a lowercase letter" do it "reports an offense when the description starts with a lowercase letter" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -108,7 +108,7 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "When the desc starts with the formula name" do it "reports an offense when the description starts with the formula name" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -118,7 +118,7 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "When the description ends with a full stop" do it "reports an offense when the description ends with a full stop" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -128,23 +128,23 @@ describe RuboCop::Cop::FormulaAudit::Desc do
RUBY RUBY
end end
it "autocorrects all rules" do it "reports and corrects all rules for description text" do
source = <<~RUBY expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
desc ' an bar: commandline foo ' desc ' an bar: commandline foo '
^ Description shouldn't have trailing spaces.
^^^^^^^^^^^ Description should use "command-line" instead of "commandline".
^ Description shouldn't have leading spaces.
end end
RUBY RUBY
correct_source = <<~RUBY expect_correction(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
desc 'Bar: command-line' desc 'Bar: command-line'
end end
RUBY RUBY
corrected_source = autocorrect_source(source, "/homebrew-core/Formula/foo.rb")
expect(corrected_source).to eq(correct_source)
end end
end end
end end

View File

@ -7,64 +7,149 @@ describe RuboCop::Cop::FormulaAudit::Homepage do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing homepage" do context "When auditing homepage" do
it "When there is no homepage" do it "reports an offense when there is no homepage" do
source = <<~RUBY expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
^^^^^^^^^^^^^^^^^^^ Formula should have a homepage.
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
end end
RUBY RUBY
expected_offenses = [{ message: "Formula should have a homepage.",
severity: :convention,
line: 1,
column: 0,
source: source }]
inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end end
it "Homepage with ftp" do it "reports an offense when the homepage is not HTTP or HTTPS" do
source = <<~RUBY expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "ftp://brew.sh/foo" homepage "ftp://brew.sh/foo"
^^^^^^^^^^^^^^^^^^^ The homepage should start with http or https.
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
end
it "reports an offense for freedesktop.org wiki pages" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "http://www.freedesktop.org/wiki/bar"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Freedesktop homepages should be styled `https://wiki.freedesktop.org/project_name`
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
end
it "reports an offense for freedesktop.org software wiki pages" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "http://www.freedesktop.org/wiki/Software/baz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Freedesktop homepages should be styled `https://wiki.freedesktop.org/www/Software/project_name`
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
end
it "reports and corrects Google Code homepages" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "https://code.google.com/p/qux"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Google Code homepages should end with a slash
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
end end
RUBY RUBY
expected_offenses = [{ message: "The homepage should start with http or " \ expect_correction(<<~RUBY)
"https (URL is ftp://brew.sh/foo).", class Foo < Formula
severity: :convention, homepage "https://code.google.com/p/qux/"
line: 2, url "https://brew.sh/foo-1.0.tgz"
column: 2, end
source: source }] RUBY
end
inspect_source(source) it "reports and corrects GitHub homepages" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "https://github.com/foo/bar.git"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GitHub homepages should not end with .git
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
expected_offenses.zip(cop.offenses).each do |expected, actual| expect_correction(<<~RUBY)
expect_offense(expected, actual) class Foo < Formula
homepage "https://github.com/foo/bar"
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
end
context "for Sourceforge" do
correct_formula = <<~RUBY
class Foo < Formula
homepage "https://foo.sourceforge.io/"
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
it "reports and corrects [1]" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "http://foo.sourceforge.net/"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sourceforge homepages should be `https://foo.sourceforge.io/`
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
expect_correction(correct_formula)
end
it "reports and corrects [2]" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "http://foo.sourceforge.net"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sourceforge homepages should be `https://foo.sourceforge.io/`
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
expect_correction(correct_formula)
end
it "reports and corrects [3]" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "http://foo.sf.net/"
^^^^^^^^^^^^^^^^^^^^ Sourceforge homepages should be `https://foo.sourceforge.io/`
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
expect_correction(correct_formula)
end end
end end
it "Homepage URLs" do it "reports and corrects readthedocs.org pages" do
expect_offense(<<~RUBY)
class Foo < Formula
homepage "https://foo.readthedocs.org"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Readthedocs homepages should be `https://foo.readthedocs.io`
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
homepage "https://foo.readthedocs.io"
url "https://brew.sh/foo-1.0.tgz"
end
RUBY
end
it "reports an offense for HTTP homepages" do
formula_homepages = { formula_homepages = {
"bar" => "http://www.freedesktop.org/wiki/bar", "sf" => "http://foo.sourceforge.io/",
"baz" => "http://www.freedesktop.org/wiki/Software/baz",
"qux" => "https://code.google.com/p/qux",
"quux" => "http://github.com/quux",
"corge" => "http://savannah.nongnu.org/corge", "corge" => "http://savannah.nongnu.org/corge",
"grault" => "http://grault.github.io/", "grault" => "http://grault.github.io/",
"garply" => "http://www.gnome.org/garply", "garply" => "http://www.gnome.org/garply",
"sf1" => "http://foo.sourceforge.net/",
"sf2" => "http://foo.sourceforge.net",
"sf3" => "http://foo.sf.net/",
"sf4" => "http://foo.sourceforge.io/",
"waldo" => "http://www.gnu.org/waldo", "waldo" => "http://www.gnu.org/waldo",
"dotgit" => "https://github.com/foo/bar.git", "dotgit" => "http://github.com/quux",
"rtd" => "https://foo.readthedocs.org",
} }
formula_homepages.each do |name, homepage| formula_homepages.each do |name, homepage|
@ -75,65 +160,19 @@ describe RuboCop::Cop::FormulaAudit::Homepage do
end end
RUBY RUBY
inspect_source(source) expected_offenses = [{ message: "Please use https:// for #{homepage}",
if homepage.include?("http://www.freedesktop.org") severity: :convention,
if homepage.include?("Software") line: 2,
expected_offenses = [{ message: "#{homepage} should be styled " \ column: 11,
"`https://wiki.freedesktop.org/www/Software/project_name`", source: source }]
severity: :convention,
line: 2, expected_offenses.zip([inspect_source(source).last]).each do |expected, actual|
column: 2, expect(actual.message).to eq(expected[:message])
source: source }] expect(actual.severity).to eq(expected[:severity])
else expect(actual.line).to eq(expected[:line])
expected_offenses = [{ message: "#{homepage} should be styled " \ expect(actual.column).to eq(expected[:column])
"`https://wiki.freedesktop.org/project_name`",
severity: :convention,
line: 2,
column: 2,
source: source }]
end
elsif homepage.include?("https://code.google.com")
expected_offenses = [{ message: "#{homepage} should end with a slash",
severity: :convention,
line: 2,
column: 2,
source: source }]
elsif homepage.match?(/foo\.(sf|sourceforge)\.net/)
expected_offenses = [{ message: "#{homepage} should be `https://foo.sourceforge.io/`",
severity: :convention,
line: 2,
column: 2,
source: source }]
elsif homepage.match?("https://github.com/foo/bar.git")
expected_offenses = [{ message: "GitHub homepages (`#{homepage}`) should not end with .git",
severity: :convention,
line: 2,
column: 11,
source: source }]
elsif homepage.match?("https://foo.readthedocs.org")
expected_offenses = [{ message: "#{homepage} should be `https://foo.readthedocs.io`",
severity: :convention,
line: 2,
column: 11,
source: source }]
else
expected_offenses = [{ message: "Please use https:// for #{homepage}",
severity: :convention,
line: 2,
column: 2,
source: source }]
end
expected_offenses.zip([cop.offenses.last]).each do |expected, actual|
expect_offense(expected, actual)
end end
end end
end end
def expect_offense(expected, actual)
expect(actual.message).to eq(expected[:message])
expect(actual.severity).to eq(expected[:severity])
expect(actual.line).to eq(expected[:line])
expect(actual.column).to eq(expected[:column])
end
end end
end end

View File

@ -6,7 +6,7 @@ require "rubocops/keg_only"
describe RuboCop::Cop::FormulaAudit::KegOnly do describe RuboCop::Cop::FormulaAudit::KegOnly do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
specify "keg_only_needs_downcasing" do it "reports and corrects an offense when the `keg_only` reason is capitalized" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
@ -17,9 +17,19 @@ describe RuboCop::Cop::FormulaAudit::KegOnly do
^^^^^^^^^^^^^^^^^ 'Because' from the `keg_only` reason should be 'because'. ^^^^^^^^^^^^^^^^^ 'Because' from the `keg_only` reason should be 'because'.
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
keg_only "because why not"
end
RUBY
end end
specify "keg_only_redundant_period" do it "reports and corrects an offense when the `keg_only` reason ends with a period" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -29,51 +39,18 @@ describe RuboCop::Cop::FormulaAudit::KegOnly do
^^^^^^^^^^^^^^^^^^^^^^^ `keg_only` reason should not end with a period. ^^^^^^^^^^^^^^^^^^^^^^^ `keg_only` reason should not end with a period.
end end
RUBY RUBY
end
specify "keg_only_autocorrects_downcasing" do expect_correction(<<~RUBY)
source = <<~RUBY
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh" homepage "https://brew.sh"
keg_only "Because why not"
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
keg_only "because why not"
end
RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
specify "keg_only_autocorrects_redundant_period" do
source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
keg_only "ending with a period."
end
RUBY
corrected_source = <<~RUBY
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
keg_only "ending with a period" keg_only "ending with a period"
end end
RUBY RUBY
new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end end
specify "keg_only_handles_block_correctly" do it "reports no offenses when a `keg_only` reason is a block" do
expect_no_offenses(<<~RUBY) expect_no_offenses(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -89,7 +66,7 @@ describe RuboCop::Cop::FormulaAudit::KegOnly do
RUBY RUBY
end end
specify "keg_only_handles_allowlist_correctly" do it "reports no offenses if a capitalized `keg-only` reason is an exempt proper noun" do
expect_no_offenses(<<~RUBY) expect_no_offenses(<<~RUBY)
class Foo < Formula class Foo < Formula
url "https://brew.sh/foo-1.0.tgz" url "https://brew.sh/foo-1.0.tgz"
@ -100,18 +77,13 @@ describe RuboCop::Cop::FormulaAudit::KegOnly do
RUBY RUBY
end end
specify "keg_only does not need downcasing of formula name in reason" do it "reports no offenses if a capitalized `keg_only` reason is the formula's name" do
filename = Formulary.core_path("foo") expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
File.open(filename, "w") do |file| class Foo < Formula
FileUtils.chmod "-rwx", filename url "https://brew.sh/foo-1.0.tgz"
expect_no_offenses(<<~RUBY, file) keg_only "Foo is the formula name hence downcasing is not required"
class Foo < Formula end
url "https://brew.sh/foo-1.0.tgz" RUBY
keg_only "Foo is the formula name hence downcasing is not required"
end
RUBY
end
end end
end end

File diff suppressed because it is too large Load Diff

View File

@ -12,12 +12,12 @@ describe RuboCop::Cop::FormulaAudit::Options do
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
option "with-32-bit" option "with-32-bit"
^^^^^^ macOS has been 64-bit only since 10.6 so 32-bit options are deprecated. ^^^^^^^^^^^^^ macOS has been 64-bit only since 10.6 so 32-bit options are deprecated.
end end
RUBY RUBY
end end
it "with universal" do it "reports an offense when using `:universal`" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -27,7 +27,7 @@ describe RuboCop::Cop::FormulaAudit::Options do
RUBY RUBY
end end
it "with bad option names" do it "reports an offense when using bad option names" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -38,7 +38,7 @@ describe RuboCop::Cop::FormulaAudit::Options do
RUBY RUBY
end end
it "with without-check option name" do it "reports an offense when using `without-check` option names" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -48,7 +48,7 @@ describe RuboCop::Cop::FormulaAudit::Options do
RUBY RUBY
end end
it "with deprecated_optionss" do it "reports an offense when using `deprecated_option` in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/") expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -58,7 +58,7 @@ describe RuboCop::Cop::FormulaAudit::Options do
RUBY RUBY
end end
it "with options" do it "reports an offense when using `option` in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/") expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'

View File

@ -7,7 +7,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
subject(:cop) { described_class.new } subject(:cop) { described_class.new }
context "When auditing legacy patches" do context "When auditing legacy patches" do
it "When there is no legacy patch" do it "reports no offenses when there is no legacy patch" do
expect_no_offenses(<<~RUBY) expect_no_offenses(<<~RUBY)
class Foo < Formula class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz' url 'https://brew.sh/foo-1.0.tgz'
@ -15,7 +15,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
RUBY RUBY
end end
it "Formula with `def patches`" do it "reports an offense if `def patches` is present" do
expect_offense(<<~RUBY) expect_offense(<<~RUBY)
class Foo < Formula class Foo < Formula
homepage "ftp://brew.sh/foo" homepage "ftp://brew.sh/foo"
@ -28,7 +28,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
RUBY RUBY
end end
it "Patch URLs" do it "reports an offense for various patch URLs" do
patch_urls = [ patch_urls = [
"https://raw.github.com/mogaal/sendemail", "https://raw.github.com/mogaal/sendemail",
"https://mirrors.ustc.edu.cn/macports/trunk/", "https://mirrors.ustc.edu.cn/macports/trunk/",
@ -48,7 +48,6 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end end
EOS EOS
inspect_source(source)
expected_offense = if patch_url.include?("/raw.github.com/") expected_offense = if patch_url.include?("/raw.github.com/")
[{ message: [{ message:
<<~EOS.chomp, <<~EOS.chomp,
@ -57,7 +56,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 12, column: 4,
source: source }] source: source }]
elsif patch_url.include?("macports/trunk") elsif patch_url.include?("macports/trunk")
[{ message: [{ message:
@ -67,7 +66,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 33, column: 4,
source: source }] source: source }]
elsif patch_url.start_with?("http://trac.macports.org") elsif patch_url.start_with?("http://trac.macports.org")
[{ message: [{ message:
@ -77,7 +76,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 5, column: 4,
source: source }] source: source }]
elsif patch_url.start_with?("http://bugs.debian.org") elsif patch_url.start_with?("http://bugs.debian.org")
[{ message: [{ message:
@ -87,7 +86,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 5, column: 4,
source: source }] source: source }]
# rubocop:disable Layout/LineLength # rubocop:disable Layout/LineLength
elsif patch_url.match?(%r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)}) elsif patch_url.match?(%r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)})
@ -95,7 +94,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
[{ message: "Use a commit hash URL rather than patch-diff: #{patch_url}", [{ message: "Use a commit hash URL rather than patch-diff: #{patch_url}",
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 5, column: 4,
source: source }] source: source }]
elsif patch_url.match?(%r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)}) elsif patch_url.match?(%r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)})
[{ message: [{ message:
@ -105,10 +104,10 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 5, column: 4,
source: source }] source: source }]
end end
expected_offense.zip([cop.offenses.last]).each do |expected, actual| expected_offense.zip([inspect_source(source).last]).each do |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])
@ -117,7 +116,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end end
end end
it "Formula with nested `def patches`" do it "reports an offense with nested `def patches`" do
source = <<~RUBY source = <<~RUBY
class Foo < Formula class Foo < Formula
homepage "ftp://brew.sh/foo" homepage "ftp://brew.sh/foo"
@ -144,12 +143,10 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 8, line: 8,
column: 26, column: 25,
source: source }] source: source }]
inspect_source(source) expected_offenses.zip(inspect_source(source)).each do |expected, actual|
expected_offenses.zip(cop.offenses).each do |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])
@ -206,7 +203,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end end
context "When auditing external patches" do context "When auditing external patches" do
it "Patch URLs" do it "reports an offense for various patch URLs" do
patch_urls = [ patch_urls = [
"https://raw.github.com/mogaal/sendemail", "https://raw.github.com/mogaal/sendemail",
"https://mirrors.ustc.edu.cn/macports/trunk/", "https://mirrors.ustc.edu.cn/macports/trunk/",
@ -230,7 +227,6 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end end
RUBY RUBY
inspect_source(source)
expected_offense = if patch_url.include?("/raw.github.com/") expected_offense = if patch_url.include?("/raw.github.com/")
[{ message: [{ message:
<<~EOS.chomp, <<~EOS.chomp,
@ -239,7 +235,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 16, column: 8,
source: source }] source: source }]
elsif patch_url.include?("macports/trunk") elsif patch_url.include?("macports/trunk")
[{ message: [{ message:
@ -249,7 +245,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 37, column: 8,
source: source }] source: source }]
elsif patch_url.start_with?("http://trac.macports.org") elsif patch_url.start_with?("http://trac.macports.org")
[{ message: [{ message:
@ -259,7 +255,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
elsif patch_url.start_with?("http://bugs.debian.org") elsif patch_url.start_with?("http://bugs.debian.org")
[{ message: [{ message:
@ -269,19 +265,19 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
elsif patch_url.match?(%r{https://github.com/[^/]*/[^/]*/pull}) elsif patch_url.match?(%r{https://github.com/[^/]*/[^/]*/pull})
[{ message: "Use a commit hash URL rather than an unstable pull request URL: #{patch_url}", [{ message: "Use a commit hash URL rather than an unstable pull request URL: #{patch_url}",
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
elsif patch_url.match?(%r{.*gitlab.*/merge_request.*}) elsif patch_url.match?(%r{.*gitlab.*/merge_request.*})
[{ message: "Use a commit hash URL rather than an unstable merge request URL: #{patch_url}", [{ message: "Use a commit hash URL rather than an unstable merge request URL: #{patch_url}",
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
elsif patch_url.match?(%r{https://github.com/[^/]*/[^/]*/commit/}) elsif patch_url.match?(%r{https://github.com/[^/]*/[^/]*/commit/})
[{ message: [{ message:
@ -291,7 +287,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
elsif patch_url.match?(%r{.*gitlab.*/commit/}) elsif patch_url.match?(%r{.*gitlab.*/commit/})
[{ message: [{ message:
@ -301,7 +297,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS EOS
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
# rubocop:disable Layout/LineLength # rubocop:disable Layout/LineLength
elsif patch_url.match?(%r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)}) elsif patch_url.match?(%r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)})
@ -309,10 +305,10 @@ describe RuboCop::Cop::FormulaAudit::Patches do
[{ message: "Use a commit hash URL rather than patch-diff: #{patch_url}", [{ message: "Use a commit hash URL rather than patch-diff: #{patch_url}",
severity: :convention, severity: :convention,
line: 5, line: 5,
column: 9, column: 8,
source: source }] source: source }]
end end
expected_offense.zip([cop.offenses.last]).each do |expected, actual| expected_offense.zip([inspect_source(source).last]).each do |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])

View File

@ -16,6 +16,13 @@ describe RuboCop::Cop::FormulaAudit::Text do
homepage "https://brew.sh" homepage "https://brew.sh"
end end
RUBY RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
homepage "https://brew.sh"
end
RUBY
end end
it "with both openssl and libressl optional dependencies" do it "with both openssl and libressl optional dependencies" do

View File

@ -200,9 +200,9 @@ describe RuboCop::Cop::FormulaAudit::Urls do
column: formula["col"], column: formula["col"],
source: source }] source: source }]
inspect_source(source) offenses = inspect_source(source)
expected_offenses.zip(cop.offenses.reverse).each do |expected, actual| expected_offenses.zip(offenses.reverse).each do |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])