Sha256: 31c25472d95664d73f67b9c2d64172b145fcad0b594d8e7de027eed235f2abde

Contents?: true

Size: 1.98 KB

Versions: 13

Compression:

Stored size: 1.98 KB

Contents

# frozen_string_literal: true

module RuboCop
  module Cop
    module Boxt
      # This cop ensures that each parameter in a Grape API has a type specified.
      #
      # @example
      #   # bad
      #   requires :name
      #   optional :age
      #
      #   # good
      #   requires :name, type: String
      #   optional :age, type: Integer
      #
      class ApiTypeParameters < RuboCop::Cop::Base
        API_MESSAGE = "Ensure each parameter has a type specified, e.g., `type: String`."
        ENTITY_MESSAGE = "Ensure each parameter has a type specified, e.g., `documentation: { type: String }`."

        def_node_matcher :param_declaration, <<-PATTERN
          (send nil? {:optional :requires :expose} _ $...)
        PATTERN

        def_node_search :param_with_type, <<-PATTERN
          (send nil? {:optional :requires} _ (hash <(pair (sym :type) $_) ...>))
        PATTERN

        def_node_search :entity_with_type_documentation, <<-PATTERN
          (send nil? :expose _ (hash <(pair (sym :documentation) (hash <(pair (sym :type) $_) ...>)) ...>))
        PATTERN

        def on_send(node)
          param_declaration(node) do
            next unless grape_api_class?(node) || grape_entity_class?(node)

            if grape_api_class?(node) && param_with_type(node).none?
              add_offense(node, message: API_MESSAGE)
            elsif grape_entity_class?(node) && entity_with_type_documentation(node).none?
              add_offense(node, message: ENTITY_MESSAGE)
            end
          end
        end

        private

        def grape_api_class?(node)
          grape_parent_class?(node, "Grape::API")
        end

        def grape_entity_class?(node)
          grape_parent_class?(node, "Grape::Entity")
        end

        def grape_parent_class?(node, class_name)
          node.each_ancestor(:class).any? do |ancestor|
            ancestor.children.any? do |child|
              child&.source == class_name
            end
          end
        end
      end
    end
  end
end

Version data entries

13 entries across 13 versions & 1 rubygems

Version Path
boxt_rubocop-2.21.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.20.1 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.20.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.19.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.18.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.17.1 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.17.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.16.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.15.1 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.15.0 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.14.3 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.14.2 lib/rubocop/cop/boxt/api_type_parameters.rb
boxt_rubocop-2.14.1 lib/rubocop/cop/boxt/api_type_parameters.rb