diff options
Diffstat (limited to 'rubocop/cop/api/grape_array_missing_coerce.rb')
-rw-r--r-- | rubocop/cop/api/grape_array_missing_coerce.rb | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/rubocop/cop/api/grape_array_missing_coerce.rb b/rubocop/cop/api/grape_array_missing_coerce.rb new file mode 100644 index 00000000000..3d7a6a72d81 --- /dev/null +++ b/rubocop/cop/api/grape_array_missing_coerce.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module API + class GrapeArrayMissingCoerce < RuboCop::Cop::Cop + # This cop checks that Grape API parameters using an Array type + # implement a coerce_with method: + # + # https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions + # + # @example + # + # # bad + # requires :values, type: Array[String] + # + # # good + # requires :values, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce + # + # end + MSG = 'This Grape parameter defines an Array but is missing a coerce_with definition. ' \ + 'For more details, see https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions' + + def_node_matcher :grape_api_instance?, <<~PATTERN + (class + (const _ _) + (const + (const + (const nil? :Grape) :API) :Instance) + ... + ) + PATTERN + + def_node_matcher :grape_api_param_block?, <<~PATTERN + (send _ {:requires :optional} + (sym _) + $_) + PATTERN + + def_node_matcher :grape_type_def?, <<~PATTERN + (sym :type) + PATTERN + + def_node_matcher :grape_array_type?, <<~PATTERN + (send + (const nil? :Array) :[] + (const nil? _)) + PATTERN + + def_node_matcher :grape_coerce_with?, <<~PATTERN + (sym :coerce_with) + PATTERN + + def on_class(node) + @grape_api ||= grape_api_instance?(node) + end + + def on_send(node) + return unless @grape_api + + match = grape_api_param_block?(node) + + return unless match.is_a?(RuboCop::AST::HashNode) + + is_array_type = false + has_coerce_method = false + + match.each_pair do |first, second| + has_coerce_method ||= grape_coerce_with?(first) + + if grape_type_def?(first) && grape_array_type?(second) + is_array_type = true + end + end + + if is_array_type && !has_coerce_method + add_offense(node) + end + end + end + end + end +end |