-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
151 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# 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 < Cop | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative "boxt/api_path_format" | ||
require_relative "boxt/api_type_parameters" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Boxt::ApiTypeParameters, :config do | ||
context "when checking Grape::API parameters" do | ||
it "does not register an offense when required parameter has type set" do | ||
expect_no_offenses(<<~RUBY) | ||
class Test < Grape::API | ||
params do | ||
requires :name, type: String | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it "does not register an offense when optional parameter has type set" do | ||
expect_no_offenses(<<~RUBY) | ||
class Test < Grape::API | ||
params do | ||
optional :age, type: Integer | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it "registers an offense when required parameter has no type set" do | ||
expect_offense(<<~RUBY) | ||
class Test < Grape::API | ||
params do | ||
requires :name | ||
^^^^^^^^^^^^^^ Ensure each parameter has a type specified, e.g., `type: String`. | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it "registers an offense when optional parameter has no type set" do | ||
expect_offense(<<~RUBY) | ||
class Test < Grape::API | ||
params do | ||
optional :age | ||
^^^^^^^^^^^^^ Ensure each parameter has a type specified, e.g., `type: String`. | ||
end | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
context "when checking Grape::Entity parameters" do | ||
it "does not register an offense when parameter has type set" do | ||
expect_no_offenses(<<~RUBY) | ||
class Test < Grape::Entity | ||
expose :name, documentation: { type: String } | ||
end | ||
RUBY | ||
end | ||
|
||
it "registers an offense when parameter has no type set" do | ||
expect_offense(<<~RUBY) | ||
class Test < Grape::Entity | ||
expose :name | ||
^^^^^^^^^^^^ Ensure each parameter has a type specified, e.g., `documentation: { type: String }`. | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
it "does not register an offense when the class isn't a Grape API" do | ||
expect_no_offenses(<<~RUBY) | ||
class Test | ||
params do | ||
requires :name | ||
end | ||
end | ||
RUBY | ||
end | ||
end |