
It now checks for two new edge cases. 1. Are the required methods defined in the block? 2. Is the `run` command defined if we're using methods other than `service_name` or `plist_name`? It has also been updated to only get the list of method call nodes once instead of doing it repeatedly for each cellar path check.
68 lines
2.4 KiB
Ruby
68 lines
2.4 KiB
Ruby
# typed: true
|
|
# frozen_string_literal: true
|
|
|
|
require "rubocops/extend/formula_cop"
|
|
|
|
module RuboCop
|
|
module Cop
|
|
module FormulaAudit
|
|
# This cop audits the service block.
|
|
#
|
|
# @api private
|
|
class Service < FormulaCop
|
|
extend AutoCorrector
|
|
|
|
CELLAR_PATH_AUDIT_CORRECTIONS = {
|
|
bin: :opt_bin,
|
|
libexec: :opt_libexec,
|
|
pkgshare: :opt_pkgshare,
|
|
prefix: :opt_prefix,
|
|
sbin: :opt_sbin,
|
|
share: :opt_share,
|
|
}.freeze
|
|
|
|
# These can be defined without using the `run` command.
|
|
RENAME_METHOD_CALLS = [:plist_name, :service_name].freeze
|
|
|
|
# At least one of these methods must be defined in a service block.
|
|
REQUIRED_METHOD_CALLS = [:run, *RENAME_METHOD_CALLS].freeze
|
|
|
|
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
|
service_node = find_block(body_node, :service)
|
|
return if service_node.blank?
|
|
|
|
method_calls = service_node.each_descendant(:send).group_by(&:method_name)
|
|
method_calls.delete(:service)
|
|
|
|
# NOTE: Solving the first problem here might solve the second one too
|
|
# so we don't show both of them at the same time.
|
|
if (method_calls.keys & REQUIRED_METHOD_CALLS).empty?
|
|
offending_node(service_node)
|
|
problem "Service blocks require `run`, `plist_name` or `service_name` to be defined."
|
|
elsif !method_calls.key?(:run)
|
|
other_method_calls = method_calls.keys - RENAME_METHOD_CALLS
|
|
if other_method_calls.any?
|
|
offending_node(service_node)
|
|
problem "`run` must be defined to use methods other than " \
|
|
"`service_name` and `plist_name` like #{other_method_calls}."
|
|
end
|
|
end
|
|
|
|
# This check ensures that cellar paths like `bin` are not referenced
|
|
# because their `opt_` variants are more portable and work with the API.
|
|
CELLAR_PATH_AUDIT_CORRECTIONS.each do |path, opt_path|
|
|
next unless method_calls.key?(path)
|
|
|
|
method_calls.fetch(path).each do |node|
|
|
offending_node(node)
|
|
problem "Use `#{opt_path}` instead of `#{path}` in service blocks." do |corrector|
|
|
corrector.replace(node.source_range, opt_path)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|