class RuboCop::Cop::Chef::Style::UnnecessaryPlatformCaseStatement

Use the platform?() and platform_family?() helpers instead of a case statement that only includes a single when statement.

@example

#### incorrect
case node['platform']
when 'ubuntu'
  log "We're on Ubuntu"
  apt_update
end

case node['platform_family']
when 'rhel'
  include_recipe 'yum'
end

#### correct
if platform?('ubuntu')
  log "We're on Ubuntu"
  apt_update
end

include_recipe 'yum' if platform_family?('rhel')

Constants

MSG

Public Instance Methods

on_case(node) click to toggle source
# File lib/rubocop/cop/chef/style/unnecessary_platform_case_statement.rb, line 56
def on_case(node)
  platform_case?(node) do |node_, type|
    return unless node&.when_branches&.count == 1
    add_offense(node, message: MSG, severity: :refactor) do |corrector|
      # we have at least one supermarket cookbook with an entirely empty platform case statement
      # we can't actually fix that so let's do nothing here.
      unless empty_case_statement?(node)
        condition_string = node.when_branches.first.conditions.map(&:source).join(', ')

        # single line bodies without an else statement should be transformed into `X if platform?('ubuntu')` style statements
        # while multi-line statements should just have the case and when bits replace with `if platform?('ubuntu')`
        if !node.else? && !node.when_branches.first.body.multiline?
          new_source = "#{node.when_branches.first.body.source} if #{type.value}?(#{condition_string})"
          corrector.replace(node, new_source)
        else
          # find the range from the beginning of the case to the end of the node['platform'] or node['platform_family']
          case_range = node.loc.keyword.join(node_.loc.expression.end)

          # replace the complete conditional range with a new if statement
          corrector.replace(case_range, "if #{type.value}?(#{condition_string})")

          # find the range from the start of the when to the end of the last argument
          conditional_range = node.when_branches.first.conditions[-1].source_range.join(node.when_branches.first.loc.keyword.begin)

          # remove the when XYZ condition along with any leading spaces so that we remove the whole empty line
          corrector.remove(range_with_surrounding_space(range: conditional_range, side: :left))
        end
      end
    end
  end
end

Private Instance Methods

empty_case_statement?(node) click to toggle source

determine if each branch of the case statement contains no code

@private

# File lib/rubocop/cop/chef/style/unnecessary_platform_case_statement.rb, line 93
def empty_case_statement?(node)
  node.else_branch.nil? && node.when_branches.all? { |x| x.body.nil? }
end