Class: RuboCop::Cop::Lint::NonAtomicFileOperation
- Extended by:
- AutoCorrector
- 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 delete unlink remove_file rm rmdir safe_unlink].freeze
- RECURSIVE_REMOVE_METHODS =
%i[remove_dir remove_entry remove_entry_secure].freeze
- RESTRICT_ON_SEND =
( MAKE_METHODS + MAKE_FORCE_METHODS + REMOVE_METHODS + RECURSIVE_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, #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_gem_version, #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
76 77 78 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 76 def_node_search :explicit_not_force?, <<~PATTERN (pair (sym :force) (:false)) PATTERN |
#force?(node) ⇒ Object
71 72 73 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 71 def_node_search :force?, <<~PATTERN (pair (sym :force) (:true)) PATTERN |
#on_send(node) ⇒ Object
80 81 82 83 84 85 86 87 88 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 80 def on_send(node) return unless node.receiver&.const_type? 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
66 67 68 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 66 def_node_matcher :receiver_and_method_name, <<~PATTERN (send (const {cbase nil?} $_) $_ ...) PATTERN |
#send_exist_node(node) ⇒ Object
61 62 63 |
# File 'lib/rubocop/cop/lint/non_atomic_file_operation.rb', line 61 def_node_search :send_exist_node, <<~PATTERN $(send (const {cbase nil?} {:FileTest :File :Dir :Shell}) {:exist? :exists?} ...) PATTERN |