Class: RuboCop::Cop::Lint::NonDeterministicRequireOrder

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector, TargetRubyVersion
Defined in:
lib/rubocop/cop/lint/non_deterministic_require_order.rb

Overview

Dir` and `Dir.glob(…)` do not make any guarantees about the order in which files are returned. The final order is determined by the operating system and file system. This means that using them in cases where the order matters, such as requiring files, can lead to intermittent failures that are hard to debug. To ensure this doesn’t happen, always sort the list.

‘Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0. So all bad cases are acceptable when Ruby 3.0 or higher are used.

NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.

Examples:


# bad
Dir["./lib/**/*.rb"].each do |file|
  require file
end

# good
Dir["./lib/**/*.rb"].sort.each do |file|
  require file
end

# bad
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')) do |file|
  require file
end

# good
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')).sort.each do |file|
  require file
end

# bad
Dir['./lib/**/*.rb'].each(&method(:require))

# good
Dir['./lib/**/*.rb'].sort.each(&method(:require))

# bad
Dir.glob(Rails.root.join('test', '*.rb'), &method(:require))

# good
Dir.glob(Rails.root.join('test', '*.rb')).sort.each(&method(:require))

# good - Respect intent if `sort` keyword option is specified in Ruby 3.0 or higher.
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb'), sort: false).each(&method(:require))

Constant Summary collapse

MSG =
'Sort files before requiring them.'

Constants inherited from Base

Base::RESTRICT_ON_SEND

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods included from TargetRubyVersion

maximum_target_ruby_version, minimum_target_ruby_version, required_maximum_ruby_version, required_minimum_ruby_version, support_target_ruby_version?

Methods inherited from Base

#active_support_extensions_enabled?, #add_global_offense, #add_offense, #always_autocorrect?, autocorrect_incompatible_with, badge, #begin_investigation, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #contextual_autocorrect?, #cop_config, cop_name, #cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, #inspect, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #parser_engine, #ready, #relevant_file?, requires_gem, #string_literals_frozen_by_default?, support_autocorrect?, support_multiple_source?, #target_rails_version, #target_ruby_version

Methods included from ExcludeLimit

#exclude_limit

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

silence_warnings

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Method Details

#on_block(node) ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/rubocop/cop/lint/non_deterministic_require_order.rb', line 68

def on_block(node)
  return unless node.body
  return unless unsorted_dir_loop?(node.send_node)

  loop_variable(node.arguments) do |var_name|
    return unless var_is_required?(node.body, var_name)

    add_offense(node.send_node) { |corrector| correct_block(corrector, node.send_node) }
  end
end

#on_block_pass(node) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rubocop/cop/lint/non_deterministic_require_order.rb', line 90

def on_block_pass(node)
  return unless method_require?(node)
  return unless unsorted_dir_pass?(node.parent)

  parent_node = node.parent

  add_offense(parent_node) do |corrector|
    if parent_node.last_argument&.block_pass_type?
      correct_block_pass(corrector, parent_node)
    else
      correct_block(corrector, parent_node)
    end
  end
end

#on_numblock(node) ⇒ Object



79
80
81
82
83
84
85
86
87
88
# File 'lib/rubocop/cop/lint/non_deterministic_require_order.rb', line 79

def on_numblock(node)
  return unless node.body
  return unless unsorted_dir_loop?(node.send_node)

  node.argument_list
      .filter { |argument| var_is_required?(node.body, argument.name) }
      .each do
        add_offense(node.send_node) { |corrector| correct_block(corrector, node.send_node) }
      end
end