class RuboCop::Cop::Rake::DuplicateTask

If tasks are defined with the same name, Rake executes the both tasks in definition order. It is misleading sometimes. You should squash them into one definition. This cop detects it.

@example

# bad
task :foo do
  p 'foo 1'
end
task :foo do
  p 'foo 2'
end

# good
task :foo do
  p 'foo 1'
  p 'foo 2'
end

Constants

MSG

Public Class Methods

new(*) click to toggle source
Calls superclass method
# File lib/rubocop/cop/rake/duplicate_task.rb, line 31
def initialize(*)
  super
  @tasks = {}
end

Public Instance Methods

message_for_dup(previous:, current:, task_name:) click to toggle source
# File lib/rubocop/cop/rake/duplicate_task.rb, line 66
def message_for_dup(previous:, current:, task_name:)
  format(
    MSG,
    task: task_name,
    previous: source_location(previous),
    current: source_location(current),
  )
end
namespaces(node) click to toggle source
# File lib/rubocop/cop/rake/duplicate_task.rb, line 52
def namespaces(node)
  ns = []

  node.each_ancestor(:block) do |block_node|
    send_node = block_node.send_node
    next unless send_node.method?(:namespace)

    name = Helper::TaskName.task_name(send_node)
    ns << name
  end

  ns
end
on_task(node) click to toggle source
# File lib/rubocop/cop/rake/duplicate_task.rb, line 36
def on_task(node)
  namespaces = namespaces(node)
  return if namespaces.include?(nil)

  task_name = Helper::TaskName.task_name(node)
  return unless task_name

  full_name = [*namespaces.reverse, task_name].join(':')
  if (previous = @tasks[full_name])
    message = message_for_dup(previous: previous, current: node, task_name: full_name)
    add_offense(node, message: message)
  else
    @tasks[full_name] = node
  end
end
source_location(node) click to toggle source
# File lib/rubocop/cop/rake/duplicate_task.rb, line 75
def source_location(node)
  range = node.location.expression
  path = smart_path(range.source_buffer.name)
  "#{path}:#{range.line}"
end