Class: RuboCop::Cop::Lint::NonAtomicFileOperation
- Extended by:
- AutoCorrector
- Includes:
- Alignment
- Defined in:
- lib/rubocop/cop/lint/non_atomic_file_operation.rb
Overview
Checks for non-atomic file operation. And then replace it with a nearly equivalent and atomic method.
These can cause problems that are difficult to reproduce, especially in cases of frequent file operations in parallel, such as test runs with parallel_rspec.
For examples: creating a directory if there is none, has the following problems
An exception occurs when the directory didn’t exist at the time of exist?, but someone else created it before mkdir was executed.
Subsequent processes are executed without the directory that should be there when the directory existed at the time of exist?, but someone else deleted it shortly afterwards.
Constant Summary collapse
- MSG_REMOVE_FILE_EXIST_CHECK =
'Remove unnecessary existence check ' \ '`%<receiver>s.%<method_name>s`.'
- MSG_CHANGE_FORCE_METHOD =
'Use atomic file operation method `FileUtils.%<method_name>s`.'- MAKE_FORCE_METHODS =
%i[makedirs mkdir_p mkpath].freeze
- MAKE_METHODS =
%i[mkdir].freeze
- REMOVE_FORCE_METHODS =
%i[rm_f rm_rf].freeze
- REMOVE_METHODS =
%i[remove remove_dir remove_entry remove_entry_secure delete unlink remove_file rm rmdir safe_unlink].freeze
- RESTRICT_ON_SEND =
(MAKE_METHODS + MAKE_FORCE_METHODS + REMOVE_METHODS + REMOVE_FORCE_METHODS).freeze
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
- #explicit_not_force?(node) ⇒ Object
- #force?(node) ⇒ Object
- #on_send(node) ⇒ Object
- #receiver_and_method_name(node) ⇒ Object
- #send_exist_node(node) ⇒ Object
Methods included from AutoCorrector
Methods inherited from Base
#active_support_extensions_enabled?, #add_global_offense, #add_offense, autocorrect_incompatible_with, badge, #begin_investigation, 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, #inspect, 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
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
Constructor Details
This class inherits a constructor from RuboCop::Cop::Base
Instance Method Details
#explicit_not_force?(node) ⇒ Object
75 76 77 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 75 def_node_search :explicit_not_force?, <<~PATTERN (pair (sym :force) (:false)) PATTERN |
#force?(node) ⇒ Object
70 71 72 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 70 def_node_search :force?, <<~PATTERN (pair (sym :force) (:true)) PATTERN |
#on_send(node) ⇒ Object
79 80 81 82 83 84 85 86 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 79 def on_send(node) return unless if_node_child?(node) return if explicit_not_force?(node) return unless (exist_node = send_exist_node(node.parent).first) return unless exist_node.first_argument == node.first_argument register_offense(node, exist_node) end |
#receiver_and_method_name(node) ⇒ Object
65 66 67 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 65 def_node_matcher :receiver_and_method_name, <<-PATTERN (send (const nil? $_) $_ ...) PATTERN |
#send_exist_node(node) ⇒ Object
60 61 62 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 60 def_node_search :send_exist_node, <<-PATTERN $(send (const nil? {:FileTest :File :Dir :Shell}) {:exist? :exists?} ...) PATTERN |