Class: RuboCop::Cop::FormulaAudit::Miscellaneous Private
- Inherits:
-
RuboCop::Cop::FormulaCop
- Object
- Base
- RuboCop::Cop::FormulaCop
- RuboCop::Cop::FormulaAudit::Miscellaneous
- Defined in:
- rubocops/lines.rb,
sorbet/rbi/dsl/rubo_cop/cop/formula_audit/miscellaneous.rbi
Overview
This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.
This cop checks for other miscellaneous style violations.
Instance Attribute Summary
Attributes inherited from RuboCop::Cop::FormulaCop
Instance Method Summary collapse
- #audit_formula(formula_nodes) ⇒ void private
- #conditional_dependencies(node, *pattern, **kwargs, &block) ⇒ T.untyped private
- #destructure_hash(node, **kwargs, &block) ⇒ T.untyped private
- #formula_path_strings(node, *pattern, **kwargs, &block) ⇒ T.untyped private
- #hash_dep(node, **kwargs, &block) ⇒ T.untyped private
- #modifier?(node) ⇒ Boolean private
Methods inherited from RuboCop::Cop::FormulaCop
#audit_comments, #audit_urls, #caveats_strings, #dependency_name_hash_match?, #dependency_type_hash_match?, #depends_on?, #depends_on_name_type?, #formula_tap, #get_checksum_node, #on_class, #required_dependency?, #required_dependency_name?, #style_exceptions_dir, #tap_style_exception?, #versioned_formula?
Methods included from HelperFunctions
#block_method_called_in_block?, #block_size, #check_precedence, #class_name, #component_precedes?, #end_column, #expression_negated?, #find_all_blocks, #find_block, #find_blocks, #find_const, #find_every_func_call_by_name, #find_every_method_call_by_name, #find_instance_call, #find_instance_method_call, #find_method_calls_by_name, #find_method_def, #find_method_with_args, #find_node_method_by_name, #find_strings, #format_component, #line_number, #line_start_column, #method_called?, #method_called_ever?, #method_name, #node_equals?, #offending_node, #parameters, #parameters_passed?, #problem, #regex_match_group, #size, #source_buffer, #start_column, #string_content
Instance Method Details
#audit_formula(formula_nodes) ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 |
# File 'rubocops/lines.rb', line 637 def audit_formula(formula_nodes) return if (body_node = formula_nodes.body_node).nil? # FileUtils is included in Formula # encfs modifies a file with this name, so check for some leading characters find_instance_method_call(body_node, "FileUtils", nil) do |method_node| problem "Don't need 'FileUtils.' before #{method_node.method_name}" end # Check for long inreplace block vars find_all_blocks(body_node, :inreplace) do |node| block_arg = node.arguments.children.first next if block_arg.source.size <= 1 problem "\"inreplace <filenames> do |s|\" is preferred over \"|#{block_arg.source}|\"." end [:rebuild, :version_scheme].each do |method_name| find_method_with_args(body_node, method_name, 0) do problem "'#{method_name} 0' should be removed" end end find_instance_call(body_node, "ARGV") do |_method_node| problem "Use build instead of ARGV to check options" end find_instance_method_call(body_node, :man, :+) do |method| next unless (match = regex_match_group(parameters(method).first, /^man[1-8]$/)) problem "\"#{method.source}\" should be \"#{match[0]}\"" end # Avoid hard-coding compilers find_every_method_call_by_name(body_node, :system).each do |method| next if @formula_name == "bazel" # TODO: Remove shim bypass in bazel. param = parameters(method).first if (match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|clang|cc|c[89]9)(\s|$)})) problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" elsif (match = regex_match_group(param, %r{^(/usr/bin/)?((g|clang|c)\+\+)(\s|$)})) problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" end end find_instance_method_call(body_node, "ENV", :[]=) do |method| next if @formula_name == "bazel" # TODO: Remove shim bypass in bazel. param = parameters(method)[1] if (match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|clang|cc|c[89]9)(\s|$)})) problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" elsif (match = regex_match_group(param, %r{^(/usr/bin/)?((g|clang|c)\+\+)(\s|$)})) problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" end end # Prefer formula path shortcuts in strings formula_path_strings(body_node, :share) do |p| next unless (match = regex_match_group(p, %r{^(/(man))/?})) problem "\"\#{share}#{match[1]}\" should be \"\#{#{match[2]}}\"" end formula_path_strings(body_node, :prefix) do |p| if (match = regex_match_group(p, %r{^(/share/(info|man))$})) problem ['"#', "{prefix}", match[1], '" should be "#{', match[2], '}"'].join end if (match = regex_match_group(p, %r{^((/share/man/)(man[1-8]))})) problem ['"#', "{prefix}", match[1], '" should be "#{', match[3], '}"'].join end if (match = regex_match_group(p, %r{^(/(bin|include|libexec|lib|sbin|share|Frameworks))}i)) problem ['"#', "{prefix}", match[1], '" should be "#{', match[2].downcase, '}"'].join end end find_every_method_call_by_name(body_node, :depends_on).each do |method| key, value = destructure_hash(parameters(method).first) next if key.nil? || value.nil? next unless (match = regex_match_group(value, /^(lua|perl|python|ruby)(\d*)/)) problem "#{match[1]} modules should be vendored rather than use deprecated `#{method.source}`" end find_every_method_call_by_name(body_node, :system).each do |method| next unless (match = regex_match_group(parameters(method).first, /^(env|export)(\s+)?/)) problem "Use ENV instead of invoking '#{match[1]}' to modify the environment" end find_every_method_call_by_name(body_node, :depends_on).each do |method| param = parameters(method).first dep, option_child_nodes = hash_dep(param) next if dep.nil? || option_child_nodes.empty? option_child_nodes.each do |option| find_strings(option).each do |dependency| next unless (match = regex_match_group(dependency, /(with(out)?-\w+|c\+\+11)/)) problem "Dependency #{string_content(dep)} should not use option #{match[0]}" end end end find_instance_method_call(body_node, :version, :==) do |method| next unless parameters_passed?(method, ["HEAD"]) problem "Use 'build.head?' instead of inspecting 'version'" end find_instance_method_call(body_node, "ARGV", :include?) do |method| next unless parameters_passed?(method, ["--HEAD"]) problem "Use \"if build.head?\" instead" end find_const(body_node, "MACOS_VERSION") do problem "Use MacOS.version instead of MACOS_VERSION" end find_const(body_node, "MACOS_FULL_VERSION") do problem "Use MacOS.full_version instead of MACOS_FULL_VERSION" end conditional_dependencies(body_node) do |node, method, param, dep_node| dep = string_content(dep_node) if node.if? if (method == :include? && regex_match_group(param, /^with-#{dep}$/)) || (method == :with? && regex_match_group(param, /^#{dep}$/)) offending_node(dep_node.parent) problem "Replace #{node.source} with #{dep_node.parent.source} => :optional" end elsif node.unless? if (method == :include? && regex_match_group(param, /^without-#{dep}$/)) || (method == :without? && regex_match_group(param, /^#{dep}$/)) offending_node(dep_node.parent) problem "Replace #{node.source} with #{dep_node.parent.source} => :recommended" end end end find_method_with_args(body_node, :fails_with, :llvm) do problem "'fails_with :llvm' is now a no-op so should be removed" end find_method_with_args(body_node, :needs, :openmp) do problem "'needs :openmp' should be replaced with 'depends_on \"gcc\"'" end find_method_with_args(body_node, :system, /^(otool|install_name_tool|lipo)/) do problem "Use ruby-macho instead of calling #{@offensive_node.source}" end problem "Use new-style test definitions (test do)" if find_method_def(body_node, :test) find_method_with_args(body_node, :skip_clean, :all) do problem "`skip_clean :all` is deprecated; brew no longer strips symbols. " \ "Pass explicit paths to prevent Homebrew from removing empty folders." end if find_method_def(processed_source.ast) problem "Define method #{method_name(@offensive_node)} in the class body, not at the top-level" end find_instance_method_call(body_node, :build, :universal?) do next if @formula_name == "wine" problem "macOS has been 64-bit only since 10.6 so build.universal? is deprecated." end find_instance_method_call(body_node, "ENV", :universal_binary) do next if @formula_name == "wine" problem "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated." end find_instance_method_call(body_node, "ENV", :runtime_cpu_detection) do next if tap_style_exception? :runtime_cpu_detection_allowlist problem "Formulae should be verified as having support for runtime hardware detection before " \ "using ENV.runtime_cpu_detection." end find_every_method_call_by_name(body_node, :depends_on).each do |method| next unless method_called?(method, :new) problem "`depends_on` can take requirement classes instead of instances" end find_instance_method_call(body_node, "ENV", :[]) do |method| next unless modifier?(method.parent) param = parameters(method).first next unless node_equals?(param, "CI") problem 'Don\'t use ENV["CI"] for Homebrew CI checks.' end find_instance_method_call(body_node, "Dir", :[]) do |method| next if parameters(method).size != 1 path = parameters(method).first next unless path.str_type? next unless (match = regex_match_group(path, /^[^*{},]+$/)) problem "Dir([\"#{string_content(path)}\"]) is unnecessary; just use \"#{match[0]}\"" end fileutils_methods = Regexp.new( FileUtils.singleton_methods(false) .map { |m| "(?-mix:^#{Regexp.escape(m)}$)" } .join("|"), ) find_every_method_call_by_name(body_node, :system).each do |method| param = parameters(method).first next unless (match = regex_match_group(param, fileutils_methods)) problem "Use the `#{match}` Ruby method instead of `#{method.source}`" end end |
#conditional_dependencies(node, *pattern, **kwargs, &block) ⇒ T.untyped
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
17 |
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_audit/miscellaneous.rbi', line 17 def conditional_dependencies(node, *pattern, **kwargs, &block); end |
#destructure_hash(node, **kwargs, &block) ⇒ T.untyped
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
20 |
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_audit/miscellaneous.rbi', line 20 def destructure_hash(node, **kwargs, &block); end |
#formula_path_strings(node, *pattern, **kwargs, &block) ⇒ T.untyped
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
30 |
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_audit/miscellaneous.rbi', line 30 def formula_path_strings(node, *pattern, **kwargs, &block); end |
#hash_dep(node, **kwargs, &block) ⇒ T.untyped
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
33 |
# File 'sorbet/rbi/dsl/rubo_cop/cop/formula_audit/miscellaneous.rbi', line 33 def hash_dep(node, **kwargs, &block); end |
#modifier?(node) ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
857 858 859 860 861 |
# File 'rubocops/lines.rb', line 857 def modifier?(node) return false unless node.if_type? node.modifier_form? end |