<commit_before># frozen_string_literal: true

module RuboCop
  module Cop
    module Style
      # This cop checks for the presence of parentheses around ternary
      # conditions. It is configurable to enforce inclusion or omission of
      # parentheses using `EnforcedStyle`. Omission is only enforced when
      # removing the parentheses won't cause a different behavior.
      #
      # @example EnforcedStyle: require_no_parentheses (default)
      #   # bad
      #   foo = (bar?) ? a : b
      #   foo = (bar.baz?) ? a : b
      #   foo = (bar && baz) ? a : b
      #
      #   # good
      #   foo = bar? ? a : b
      #   foo = bar.baz? ? a : b
      #   foo = bar && baz ? a : b
      #
      # @example EnforcedStyle: require_parentheses
      #   # bad
      #   foo = bar? ? a : b
      #   foo = bar.baz? ? a : b
      #   foo = bar && baz ? a : b
      #
      #   # good
      #   foo = (bar?) ? a : b
      #   foo = (bar.baz?) ? a : b
      #   foo = (bar && baz) ? a : b
      #
      # @example EnforcedStyle: require_parentheses_when_complex
      #   # bad
      #   foo = (bar?) ? a : b
      #   foo = (bar.baz?) ? a : b
      #   foo = bar && baz ? a : b
      #
      #   # good
      #   foo = bar? ? a : b
      #   foo = bar.baz? ? a : b
      #   foo = (bar && baz) ? a : b
      class TernaryParentheses < Cop
        include SafeAssignment
        include ConfigurableEnforcedStyle
        include SurroundingSpace

        VARIABLE_TYPES = AST::Node::VARIABLES
        NON_COMPLEX_TYPES = [*VARIABLE_TYPES, :const, :defined?, :yield].freeze

        MSG = '%<command>s parentheses for ternary conditions.'.freeze
        MSG_COMPLEX = '%<command>s parentheses for ternary expressions with' \
          ' complex conditions.'.freeze

        def on_if(node)
          return unless node.ternary? && !infinite_loop? && offense?(node)

          add_offense(node, location: node.source_range)
        end

        def autocorrect(node)
          condition = node.condition

          return nil if parenthesized?(condition) &&
                        (safe_assignment?(condition) ||
                        unsafe_autocorrect?(condition))

          if parenthesized?(condition)
            correct_parenthesized(condition)
          else
            correct_unparenthesized(condition)
          end
        end

        private

        def offense?(node)
          condition = node.condition

          if safe_assignment?(condition)
            !safe_assignment_allowed?
          else
            parens = parenthesized?(condition)
            case style
            when :require_parentheses_when_complex
              complex_condition?(condition) ? !parens : parens
            else
              require_parentheses? ? !parens : parens
            end
          end
        end

        # If the condition is parenthesized we recurse and check for any
        # complex expressions within it.
        def complex_condition?(condition)
          if condition.begin_type?
            condition.to_a.any? { |x| complex_condition?(x) }
          else
            non_complex_expression?(condition) ? false : true
          end
        end

        # Anything that is not a variable, constant, or method/.method call
        # will be counted as a complex expression.
        def non_complex_expression?(condition)
          NON_COMPLEX_TYPES.include?(condition.type) ||
            non_complex_send?(condition)
        end

        def non_complex_send?(node)
          return false unless node.send_type?

          !node.operator_method? || node.method?(:[])
        end

        def message(node)
          if require_parentheses_when_complex?
            command = parenthesized?(node.condition) ? 'Only use' : 'Use'
            format(MSG_COMPLEX, command: command)
          else
            command = require_parentheses? ? 'Use' : 'Omit'
            format(MSG, command: command)
          end
        end

        def require_parentheses?
          style == :require_parentheses
        end

        def require_parentheses_when_complex?
          style == :require_parentheses_when_complex
        end

        def redundant_parentheses_enabled?
          @config.for_cop('Style/RedundantParentheses').fetch('Enabled')
        end

        def parenthesized?(node)
          node.begin_type?
        end

        # When this cop is configured to enforce parentheses and the
        # `RedundantParentheses` cop is enabled, it will cause an infinite loop
        # as they compete to add and remove the parentheses respectively.
        def infinite_loop?
          require_parentheses? &&
            redundant_parentheses_enabled?
        end

        def unsafe_autocorrect?(condition)
          condition.children.any? do |child|
            unparenthesized_method_call?(child)
          end
        end

        def unparenthesized_method_call?(child)
          argument = method_call_argument(child)
          argument && argument !~ /^\(/
        end

        def_node_matcher :method_call_argument, <<-PATTERN
          {(:defined? $...)
           (send {_ nil?} _ $(send nil? _)...)}<commit_msg>Replace regular expression usage in TernaryParentheses cop<commit_after># frozen_string_literal: true

module RuboCop
  module Cop
    module Style
      # This cop checks for the presence of parentheses around ternary
      # conditions. It is configurable to enforce inclusion or omission of
      # parentheses using `EnforcedStyle`. Omission is only enforced when
      # removing the parentheses won't cause a different behavior.
      #
      # @example EnforcedStyle: require_no_parentheses (default)
      #   # bad
      #   foo = (bar?) ? a : b
      #   foo = (bar.baz?) ? a : b
      #   foo = (bar && baz) ? a : b
      #
      #   # good
      #   foo = bar? ? a : b
      #   foo = bar.baz? ? a : b
      #   foo = bar && baz ? a : b
      #
      # @example EnforcedStyle: require_parentheses
      #   # bad
      #   foo = bar? ? a : b
      #   foo = bar.baz? ? a : b
      #   foo = bar && baz ? a : b
      #
      #   # good
      #   foo = (bar?) ? a : b
      #   foo = (bar.baz?) ? a : b
      #   foo = (bar && baz) ? a : b
      #
      # @example EnforcedStyle: require_parentheses_when_complex
      #   # bad
      #   foo = (bar?) ? a : b
      #   foo = (bar.baz?) ? a : b
      #   foo = bar && baz ? a : b
      #
      #   # good
      #   foo = bar? ? a : b
      #   foo = bar.baz? ? a : b
      #   foo = (bar && baz) ? a : b
      class TernaryParentheses < Cop
        include SafeAssignment
        include ConfigurableEnforcedStyle
        include SurroundingSpace

        VARIABLE_TYPES = AST::Node::VARIABLES
        NON_COMPLEX_TYPES = [*VARIABLE_TYPES, :const, :defined?, :yield].freeze

        MSG = '%<command>s parentheses for ternary conditions.'.freeze
        MSG_COMPLEX = '%<command>s parentheses for ternary expressions with' \
          ' complex conditions.'.freeze

        def on_if(node)
          return unless node.ternary? && !infinite_loop? && offense?(node)

          add_offense(node, location: node.source_range)
        end

        def autocorrect(node)
          condition = node.condition

          return nil if parenthesized?(condition) &&
                        (safe_assignment?(condition) ||
                        unsafe_autocorrect?(condition))

          if parenthesized?(condition)
            correct_parenthesized(condition)
          else
            correct_unparenthesized(condition)
          end
        end

        private

        def offense?(node)
          condition = node.condition

          if safe_assignment?(condition)
            !safe_assignment_allowed?
          else
            parens = parenthesized?(condition)
            case style
            when :require_parentheses_when_complex
              complex_condition?(condition) ? !parens : parens
            else
              require_parentheses? ? !parens : parens
            end
          end
        end

        # If the condition is parenthesized we recurse and check for any
        # complex expressions within it.
        def complex_condition?(condition)
          if condition.begin_type?
            condition.to_a.any? { |x| complex_condition?(x) }
          else
            non_complex_expression?(condition) ? false : true
          end
        end

        # Anything that is not a variable, constant, or method/.method call
        # will be counted as a complex expression.
        def non_complex_expression?(condition)
          NON_COMPLEX_TYPES.include?(condition.type) ||
            non_complex_send?(condition)
        end

        def non_complex_send?(node)
          return false unless node.send_type?

          !node.operator_method? || node.method?(:[])
        end

        def message(node)
          if require_parentheses_when_complex?
            command = parenthesized?(node.condition) ? 'Only use' : 'Use'
            format(MSG_COMPLEX, command: command)
          else
            command = require_parentheses? ? 'Use' : 'Omit'
            format(MSG, command: command)
          end
        end

        def require_parentheses?
          style == :require_parentheses
        end

        def require_parentheses_when_complex?
          style == :require_parentheses_when_complex
        end

        def redundant_parentheses_enabled?
          @config.for_cop('Style/RedundantParentheses').fetch('Enabled')
        end

        def parenthesized?(node)
          node.begin_type?
        end

        # When this cop is configured to enforce parentheses and the
        # `RedundantParentheses` cop is enabled, it will cause an infinite loop
        # as they compete to add and remove the parentheses respectively.
        def infinite_loop?
          require_parentheses? &&
            redundant_parentheses_enabled?
        end

        def unsafe_autocorrect?(condition)
          condition.children.any? do |child|
            unparenthesized_method_call?(child)
          end
        end

        def unparenthesized_method_call?(child)
          argument = method_call_argument(child)

          argument && !argument.parenthesized?
        end

        def_node_matcher :method_call_argument, <<-PATTERN
          {(:defined? $(send nil? _) ...)
           (send {_ nil?} _ $(send nil? _) ...)}
{'fraction_non_alphanumeric': 0.08688524590163935, 'fraction_numerical': 0.0, 'mean_word_length': 1.8151465798045603, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7049246', 'n_tokens_mistral': 2994, 'n_tokens_neox': 2883, 'n_words': 768}