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

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
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.

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 inherited from Base

#add_global_offense, #add_offense, autocorrect_incompatible_with, badge, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, #cop_name, cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #ready, #relevant_file?, 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?, #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


61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rubocop/cop/lint/non_deterministic_require_order.rb', line 61

def on_block(node)
  return if target_ruby_version >= 3.0
  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


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rubocop/cop/lint/non_deterministic_require_order.rb', line 73

def on_block_pass(node)
  return if target_ruby_version >= 3.0
  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.arguments.last&.block_pass_type?
      correct_block_pass(corrector, parent_node)
    else
      correct_block(corrector, parent_node)
    end
  end
end