Class: RuboCop::Cop::FormulaAudit::Miscellaneous Private
- Inherits:
-
RuboCop::Cop::FormulaCop
- Object
- Base
- RuboCop::Cop::FormulaCop
- RuboCop::Cop::FormulaAudit::Miscellaneous
- Defined in:
- rubocops/lines.rb
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(_node, _class_node, _parent_class_node, body_node) ⇒ Object
private
-
#modifier?(node) ⇒ Boolean
private
Methods inherited from RuboCop::Cop::FormulaCop
#audit_comments, #audit_urls, #caveats_strings, #depends_on?, #depends_on_name_type?, #formula_tap, #get_checksum_node, #on_class, #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(_node, _class_node, _parent_class_node, body_node) ⇒ Object
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.
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 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 |
# File 'rubocops/lines.rb', line 462 def audit_formula(_node, _class_node, _parent_class_node, body_node) # 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 unless 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| param = parameters(method).first if (match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|llvm-gcc|clang)(\s|$)})) problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" elsif (match = regex_match_group(param, %r{^(/usr/bin/)?((g|llvm-g|clang)\+\+)(\s|$)})) problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" end end find_instance_method_call(body_node, "ENV", :[]=) do |method| param = parameters(method)[1] if (match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|llvm-gcc|clang)(\s|$)})) problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" elsif (match = regex_match_group(param, %r{^(/usr/bin/)?((g|llvm-g|clang)\+\+)(\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]}}\"" end if (match = regex_match_group(p, %r{^((/share/man/)(man[1-8]))})) problem "\"\#\{prefix}#{match[1]}\" should be \"\#{#{match[3]}}\"" 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}}\"" 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 find_every_method_call_by_name(body_node, :system).each do |method_node| # Skip Kibana: npm cache edge (see formula for more details) next if @formula_name.match?(/^kibana(@\d[\d.]*)?$/) first_param, second_param = parameters(method_node) next if !node_equals?(first_param, "npm") || !node_equals?(second_param, "install") offending_node(method_node) problem "Use Language::Node for npm install args" unless languageNodeModule?(method_node) 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 unless 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 |
#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.
688 689 690 691 692 |
# File 'rubocops/lines.rb', line 688 def modifier?(node) return false unless node.if_type? node.modifier_form? end |