\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef.upgrade/embedded/lib/ruby/gems/2.3.0/gems/rubocop-0.47.1/lib/rubocop/cop/style/

Viewing File: lambda.rb

# frozen_string_literal: true

module RuboCop
  module Cop
    module Style
      # This cop (by default) checks for uses of the lambda literal syntax for
      # single line lambdas, and the method call syntax for multiline lambdas.
      # It is configurable to enforce one of the styles for both single line
      # and multiline lambdas as well.
      #
      # @example
      #
      #   # EnforcedStyle: line_count_dependent (default)
      #
      #   # bad
      #   f = lambda { |x| x }
      #   f = ->(x) do
      #         x
      #       end
      #
      #   # good
      #   f = ->(x) { x }
      #   f = lambda do |x|
      #         x
      #       end
      #
      # @example
      #
      #   # EnforcedStyle: lambda
      #
      #   # bad
      #   f = ->(x) { x }
      #   f = ->(x) do
      #         x
      #       end
      #
      #   # good
      #   f = lambda { |x| x }
      #   f = lambda do |x|
      #         x
      #       end
      #
      # @example
      #
      #   # EnforcedStyle: literal
      #
      #   # bad
      #   f = lambda { |x| x }
      #   f = lambda do |x|
      #         x
      #       end
      #
      #   # good
      #   f = ->(x) { x }
      #   f = ->(x) do
      #         x
      #       end
      class Lambda < Cop
        include ConfigurableEnforcedStyle

        LITERAL_MESSAGE = 'Use the `-> { ... }` lambda literal syntax for ' \
                          '%s lambdas.'.freeze
        METHOD_MESSAGE = 'Use the `lambda` method for %s lambdas.'.freeze

        OFFENDING_SELECTORS = {
          style: {
            lambda: { single_line: '->', multiline: '->' },
            literal: { single_line: 'lambda', multiline: 'lambda' },
            line_count_dependent: { single_line: 'lambda', multiline: '->' }
          }
        }.freeze

        def_node_matcher :lambda_node?, '(block $(send nil :lambda) ...)'

        def on_block(node)
          lambda_node?(node) do |block_method|
            selector = block_method.source

            return unless offending_selector?(node, selector)

            add_offense(node,
                        block_method.source_range,
                        message(node, selector))
          end
        end

        private

        def offending_selector?(node, selector)
          lines = node.multiline? ? :multiline : :single_line

          selector == OFFENDING_SELECTORS[:style][style][lines]
        end

        def message(node, selector)
          message = selector == '->' ? METHOD_MESSAGE : LITERAL_MESSAGE

          format(message, message_line_modifier(node))
        end

        def message_line_modifier(node)
          case style
          when :line_count_dependent
            node.multiline? ? 'multiline' : 'single line'
          else
            'all'
          end
        end

        def autocorrect(node)
          block_method, _args = *node
          selector = block_method.source

          # Don't autocorrect if this would change the meaning of the code
          return if selector == '->' && arg_to_unparenthesized_call?(node)

          lambda do |corrector|
            if selector == 'lambda'
              autocorrect_method_to_literal(corrector, node)
            else
              autocorrect_literal_to_method(corrector, node)
            end
          end
        end

        def autocorrect_literal_to_method(corrector, node)
          block_method, args = *node

          # Check for unparenthesized args' preceding and trailing whitespaces.
          remove_unparenthesized_whitespaces(corrector, node)

          # Avoid correcting to `lambdado` by inserting whitespace
          # if none exists before or after the lambda arguments.
          if needs_whitespace?(block_method, args, node)
            corrector.insert_before(node.loc.begin, ' ')
          end
          corrector.replace(block_method.source_range, 'lambda')
          corrector.remove(args.source_range) if args.source_range
          return if args.children.empty?
          arg_str = " |#{lambda_arg_string(args)}|"
          corrector.insert_after(node.loc.begin, arg_str)
        end

        def autocorrect_method_to_literal(corrector, node)
          block_method, args = *node
          corrector.replace(block_method.source_range, '->')
          return if args.children.empty?

          arg_str = "(#{lambda_arg_string(args)})"
          whitespace_and_old_args = node.loc.begin.end.join(args.loc.end)
          corrector.insert_after(block_method.source_range, arg_str)
          corrector.remove(whitespace_and_old_args)
        end

        def needs_whitespace?(block_method, args, node)
          selector_end = block_method.loc.selector.end.end_pos
          block_begin  = node.loc.begin.begin_pos

          (block_begin == end_pos(args) && selector_end == begin_pos(args)) ||
            (block_begin == selector_end)
        end

        def begin_pos(node)
          node.loc.begin && node.loc.begin.begin_pos
        end

        def end_pos(node)
          node.loc.end && node.loc.end.end_pos
        end

        def lambda_arg_string(args)
          args.children.map(&:source).join(', ')
        end

        def arg_to_unparenthesized_call?(arg_node)
          parent = arg_node.parent

          if parent && parent.pair_type?
            arg_node = parent.parent
            parent = arg_node.parent
          end

          return false unless parent && parent.send_type?
          return false if parenthesized_call?(parent)

          arg_node.sibling_index > 1
        end

        def remove_unparenthesized_whitespaces(corrector, node)
          block_method, args = *node
          return unless unparenthesized_literal_args?(args)
          # First, remove leading whitespaces (beetween arrow and args)
          corrector.remove_preceding(
            args.source_range,
            args.source_range.begin_pos - block_method.source_range.end_pos
          )

          # Then, remove trailing whitespaces (beetween args and 'do')
          delta = node.loc.begin.begin_pos - args.source_range.end_pos - 1
          corrector.remove_preceding(node.loc.begin, delta)
        end

        def unparenthesized_literal_args?(args)
          args.source_range && args.source_range.begin && !parentheses?(args)
        end
      end
    end
  end
end