diff options
Diffstat (limited to 'rubocop')
-rw-r--r-- | rubocop/cop/rake/require.rb | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/rubocop/cop/rake/require.rb b/rubocop/cop/rake/require.rb new file mode 100644 index 00000000000..e3e1696943d --- /dev/null +++ b/rubocop/cop/rake/require.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Rake + # Flag global `require`s or `require_relative`s in rake files. + # + # Load dependencies lazily in `task` definitions if possible. + # + # @example + # # bad + # + # require_relative 'gitlab/json' + # require 'json' + # + # task :parse_json do + # Gitlab::Json.parse(...) + # end + # + # # good + # + # task :parse_json do + # require_relative 'gitlab/json' + # require 'json' + # + # Gitlab::Json.parse(...) + # end + # + # RSpec::Core::RakeTask.new(:parse_json) do |t, args| + # require_relative 'gitlab/json' + # require 'json' + # + # Gitlab::Json.parse(...) + # end + # + # # Requiring files which contain the word `task` is allowed. + # require 'some_gem/rake_task' + # require 'some_gem/rake_tasks' + # + # SomeGem.define_tasks + # + # # Loading in method definition as well. + # def load_deps + # require 'json' + # end + # + # task :parse_json + # load_deps + # end + # + class Require < RuboCop::Cop::Base + MSG = 'Load dependencies inside `task` definitions if possible.' + + METHODS = %i[require require_relative].freeze + RESTRICT_ON_SEND = METHODS + + def_node_matcher :require_method, <<~PATTERN + (send nil? ${#{METHODS.map(&:inspect).join(' ')}} $_) + PATTERN + + def on_send(node) + method, file = require_method(node) + return unless method + + return if requires_task?(file) + return if inside_block_or_method?(node) + + add_offense(node) + end + + private + + # Allow `require "foo/rake_task"` + def requires_task?(file) + file.source.include?('task') + end + + def inside_block_or_method?(node) + node.each_ancestor(:block, :def).any? + end + end + end + end +end |