rubocop-graphql 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cdf5152e0106f86e952fbf5a24a38011914f34b0167a19ef0cf53dd810e4d68
4
- data.tar.gz: 9ed0ac94bdc4f323543e1085a612dfb3d02f5e60ee55892da6894b202718865e
3
+ metadata.gz: b6b8cbd4a0d9dec84fd66e8fd76716d4d23d1a6ce486c713a951cd6c375255dd
4
+ data.tar.gz: 9f7b85517392c031a54e63d9cbd28280cf41d9afb890f67f8e4054fc0704e553
5
5
  SHA512:
6
- metadata.gz: 992563e33d74e91766b4917a541ef9361795156f93eb33a95f0944e4968f87a5845681adff07178a30cd11b10c6b2e10ea002e2688b2a501cc6b9e25bb1bc103
7
- data.tar.gz: 2cf037f19ca63a512ea00a06601cf49dcc46ed5bb59deec1ede2e45dcd74acfd875b7febf7f703b36354fa4059dd222ca5f37fb59a11572c7cc8d4ffb97389a9
6
+ metadata.gz: 3474232c9c512d5b86d3c8fd43b790562b01ac458786e96c3c34a1556f530390fff21bd55a7805c382278b43d6c13cb336307b987ce070cbab01788e3c6e5194
7
+ data.tar.gz: f8c5fba9247ad3ce42131b4bd3ee8dfd7f623eb896ca7cce9fb6e0f6ad29c6d38ce616f877e0a5d92dedc8a7701110cd37334fd9af1cb042bcc130285fa2b7d6
data/config/default.yml CHANGED
@@ -134,6 +134,8 @@ GraphQL/ObjectDescription:
134
134
  VersionAdded: '0.3.0'
135
135
  Description: 'Ensures all types have a description'
136
136
  Exclude:
137
+ - "spec/**/*"
138
+ - "test/**/*"
137
139
  - '**/*_schema.rb'
138
140
  - '**/base_*.rb'
139
141
  - '**/graphql/query_context.rb'
@@ -22,6 +22,7 @@ module RuboCop
22
22
  include RuboCop::GraphQL::NodePattern
23
23
 
24
24
  MSG = "Missing argument description"
25
+ RESTRICT_ON_SEND = %i[argument].freeze
25
26
 
26
27
  def on_send(node)
27
28
  return unless argument?(node)
@@ -20,6 +20,7 @@ module RuboCop
20
20
  #
21
21
  class ArgumentName < Base
22
22
  include RuboCop::GraphQL::NodePattern
23
+ RESTRICT_ON_SEND = %i[argument].freeze
23
24
 
24
25
  using RuboCop::GraphQL::Ext::SnakeCase
25
26
 
@@ -52,6 +52,8 @@ module RuboCop
52
52
  include RuboCop::GraphQL::Sorbet
53
53
  include RuboCop::GraphQL::Heredoc
54
54
 
55
+ RESTRICT_ON_SEND = %i[field].freeze
56
+
55
57
  # @!method field_kwargs(node)
56
58
  def_node_matcher :field_kwargs, <<~PATTERN
57
59
  (send nil? :field
@@ -22,6 +22,7 @@ module RuboCop
22
22
  include RuboCop::GraphQL::NodePattern
23
23
 
24
24
  MSG = "Missing field description"
25
+ RESTRICT_ON_SEND = %i[field].freeze
25
26
 
26
27
  def on_send(node)
27
28
  return unless field_definition?(node)
@@ -41,6 +41,7 @@ module RuboCop
41
41
  PATTERN
42
42
 
43
43
  MSG = "Use hash_key: %<hash_key>p"
44
+ RESTRICT_ON_SEND = %i[field].freeze
44
45
 
45
46
  def on_send(node)
46
47
  return unless field_definition?(node)
@@ -40,6 +40,7 @@ module RuboCop
40
40
  PATTERN
41
41
 
42
42
  MSG = "Use method: :%<method_name>s"
43
+ RESTRICT_ON_SEND = %i[field].freeze
43
44
 
44
45
  def on_send(node)
45
46
  return unless field_definition?(node)
@@ -29,6 +29,7 @@ module RuboCop
29
29
  using RuboCop::GraphQL::Ext::SnakeCase
30
30
 
31
31
  MSG = "Use snake_case for field names"
32
+ RESTRICT_ON_SEND = %i[field].freeze
32
33
 
33
34
  def on_send(node)
34
35
  return unless field_definition?(node)
@@ -63,9 +63,16 @@ module RuboCop
63
63
  end
64
64
 
65
65
  def field_name(node)
66
- node.first_argument.value.to_s
66
+ field = RuboCop::GraphQL::Field.new(node)
67
+
68
+ "#{field.name}#{':non-camelized' if false_value?(field.kwargs.camelize)}"
67
69
  end
68
70
 
71
+ # @!method false_value?(node)
72
+ def_node_matcher :false_value?, <<~PATTERN
73
+ (pair ... false)
74
+ PATTERN
75
+
69
76
  # @!method field_declarations(node)
70
77
  def_node_search :field_declarations, <<~PATTERN
71
78
  {
@@ -32,6 +32,7 @@ module RuboCop
32
32
 
33
33
  MSG = "Avoid using legacy based type-based definitions. " \
34
34
  "Use class-based definitions instead."
35
+ RESTRICT_ON_SEND = %i[define].freeze
35
36
 
36
37
  def on_send(node)
37
38
  return unless node.parent.block_type?
@@ -32,6 +32,8 @@ module RuboCop
32
32
  include RuboCop::Cop::RangeHelp
33
33
  include RuboCop::GraphQL::Heredoc
34
34
 
35
+ RESTRICT_ON_SEND = %i[field].freeze
36
+
35
37
  def on_send(node)
36
38
  return unless field?(node)
37
39
 
@@ -10,6 +10,9 @@ module RuboCop
10
10
  # If `.authorized?` is defined in a parent class, you can add parent to the "SafeBaseClasses"
11
11
  # to avoid offenses in children.
12
12
  #
13
+ # This cop also checks the `can_can_action` or `pundit_role` methods that
14
+ # can be used as part of the Ruby GraphQL Pro.
15
+ #
13
16
  # @example
14
17
  # # good
15
18
  #
@@ -37,6 +40,26 @@ module RuboCop
37
40
  # end
38
41
  # end
39
42
  #
43
+ # # good
44
+ #
45
+ # class UserType < BaseType
46
+ # implements GraphQL::Types::Relay::Node
47
+ #
48
+ # pundit_role :staff
49
+ #
50
+ # field :uuid, ID, null: false
51
+ # end
52
+ #
53
+ # # good
54
+ #
55
+ # class UserType < BaseType
56
+ # implements GraphQL::Types::Relay::Node
57
+ #
58
+ # can_can_action :staff
59
+ #
60
+ # field :uuid, ID, null: false
61
+ # end
62
+ #
40
63
  # # bad
41
64
  #
42
65
  # class UserType < BaseType
@@ -48,11 +71,6 @@ module RuboCop
48
71
  class NotAuthorizedNodeType < Base
49
72
  MSG = ".authorized? should be defined for types implementing Node interface."
50
73
 
51
- # @!method class_name(node)
52
- def_node_matcher :class_name, <<~PATTERN
53
- (const nil? $_)
54
- PATTERN
55
-
56
74
  # @!method implements_node_type?(node)
57
75
  def_node_matcher :implements_node_type?, <<~PATTERN
58
76
  `(send nil? :implements
@@ -62,25 +80,53 @@ module RuboCop
62
80
  (const nil? :GraphQL) :Types) :Relay) :Node))
63
81
  PATTERN
64
82
 
83
+ # @!method has_can_can_action?(node)
84
+ def_node_matcher :has_can_can_action?, <<~PATTERN
85
+ `(send nil? :can_can_action {nil_type? sym_type?})
86
+ PATTERN
87
+
88
+ # @!method has_pundit_role?(node)
89
+ def_node_matcher :has_pundit_role?, <<~PATTERN
90
+ `(send nil? :pundit_role {nil_type? sym_type?})
91
+ PATTERN
92
+
65
93
  # @!method has_authorized_method?(node)
66
94
  def_node_matcher :has_authorized_method?, <<~PATTERN
67
95
  {`(:defs (:self) :authorized? ...) | `(:sclass (:self) `(:def :authorized? ...))}
68
96
  PATTERN
69
97
 
98
+ def on_module(node)
99
+ @parent_modules ||= []
100
+ @parent_modules << node.child_nodes[0].const_name
101
+ end
102
+
70
103
  def on_class(node)
71
- return if ignored_class?(parent_class(node))
104
+ @parent_modules ||= []
105
+ return if possible_parent_classes(node).any? { |klass| ignored_class?(klass) }
106
+
107
+ @parent_modules << node.child_nodes[0].const_name
72
108
 
73
- add_offense(node) if implements_node_type?(node) && !has_authorized_method?(node)
109
+ add_offense(node) if implements_node_type?(node) && !implements_authorization?(node)
74
110
  end
75
111
 
76
112
  private
77
113
 
78
- def parent_class(node)
79
- node.child_nodes[1]
114
+ def implements_authorization?(node)
115
+ has_authorized_method?(node) || has_can_can_action?(node) || has_pundit_role?(node)
116
+ end
117
+
118
+ def possible_parent_classes(node)
119
+ klass = node.child_nodes[1].const_name
120
+
121
+ return [] if klass.nil?
122
+ return [klass] if node.child_nodes[1].absolute?
123
+
124
+ parent_module = "#{@parent_modules.join('::')}::"
125
+ [klass, parent_module + klass]
80
126
  end
81
127
 
82
- def ignored_class?(node)
83
- cop_config["SafeBaseClasses"].include?(String(class_name(node)))
128
+ def ignored_class?(klass)
129
+ cop_config["SafeBaseClasses"].include?(klass)
84
130
  end
85
131
  end
86
132
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module GraphQL
8
+ # Checks that GraphQL Argument definitions prepare arguments use String or constants
9
+ # instead of `prepare: CONST_REF`
10
+ # This allows better Sorbet typing.
11
+ #
12
+ # Preference is given to an input object declaring a `def prepare(...); end` method
13
+ #
14
+ # @example
15
+ # # bad
16
+ # PREPARE = ->(input, context) { ... }
17
+ #
18
+ # argument :input, prepare: PREPARE
19
+ #
20
+ # # good
21
+ # def input_prepare(input); ...; end
22
+ #
23
+ # argument :input, prepare: :input_prepare
24
+ #
25
+ class PrepareMethod < RuboCop::Cop::Base
26
+ extend AutoCorrector
27
+ GENERAL_MSG = "Avoid using prepare lambdas, use prepare: :method_name or "\
28
+ "prepare: \"method_name\" instead."
29
+ STRING_MSG = "Avoid using prepare lambdas, use prepare: \"method_name\" instead."
30
+ PREFER_STRING_MSG = "Avoid using prepare symbols, use prepare: \"%s\" instead."
31
+ SYMBOL_MSG = "Avoid using prepare lambdas, use prepare: :method_name instead."
32
+ PREFER_SYMBOL_MSG = "Avoid using prepare string, use prepare: :%s instead."
33
+
34
+ ARGUMENT_METHODS = Set[:argument, :public_argument].freeze
35
+
36
+ # @!method graphql_argument_with_prepare_block?(node)
37
+ def_node_matcher :graphql_argument_with_prepare_block?, <<~PATTERN
38
+ (send nil? ARGUMENT_METHODS ... (hash ... (pair (sym :prepare) $({ const | block } ...) )))
39
+ PATTERN
40
+
41
+ # @!method prepare_method_string_name?(node)
42
+ def_node_matcher :prepare_method_string_name?, <<~PATTERN
43
+ (send nil? ARGUMENT_METHODS ... (hash ... (pair (sym :prepare) $(str ...) )))
44
+ PATTERN
45
+
46
+ # @!method prepare_method_symbol_name?(node)
47
+ def_node_matcher :prepare_method_symbol_name?, <<~PATTERN
48
+ (send nil? ARGUMENT_METHODS ... (hash ... (pair (sym :prepare) $(sym ...) )))
49
+ PATTERN
50
+
51
+ def on_send(node)
52
+ type = cop_config["EnforcedStyle"]
53
+
54
+ message = case type
55
+ when "symbol"
56
+ SYMBOL_MSG
57
+ when "string"
58
+ STRING_MSG
59
+ else
60
+ GENERAL_MSG
61
+ end
62
+ graphql_argument_with_prepare_block?(node) do |prepare_definition|
63
+ add_offense(prepare_definition, message: message)
64
+ end
65
+
66
+ if type == "symbol"
67
+ prepare_method_string_name?(node) do |prepare_definition|
68
+ method_name = prepare_definition.value
69
+ add_offense(prepare_definition,
70
+ message: format(PREFER_SYMBOL_MSG, method_name)) do |corrector|
71
+ autocorrect(corrector, node, "\"#{method_name}\"", ":#{method_name}")
72
+ end
73
+ end
74
+ elsif type == "string"
75
+ prepare_method_symbol_name?(node) do |prepare_definition|
76
+ method_name = prepare_definition.value
77
+ add_offense(prepare_definition,
78
+ message: format(PREFER_STRING_MSG, method_name)) do |corrector|
79
+ autocorrect(corrector, node, ":#{method_name}", "\"#{method_name}\"")
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def autocorrect(corrector, node, original_method_name, new_method_name)
88
+ new_source = node.source.sub("prepare: #{original_method_name}",
89
+ "prepare: #{new_method_name}")
90
+ corrector.replace(node, new_source)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -44,6 +44,7 @@ module RuboCop
44
44
  include RuboCop::GraphQL::NodePattern
45
45
 
46
46
  MSG = "Unnecessary argument camelize"
47
+ RESTRICT_ON_SEND = %i[argument].freeze
47
48
 
48
49
  def on_send(node)
49
50
  return unless argument?(node)
@@ -25,6 +25,7 @@ module RuboCop
25
25
  include RuboCop::GraphQL::NodePattern
26
26
 
27
27
  MSG = "Unnecessary :%<kwarg>s configured"
28
+ RESTRICT_ON_SEND = %i[field].freeze
28
29
 
29
30
  def on_send(node)
30
31
  return unless field_definition?(node)
@@ -34,7 +35,7 @@ module RuboCop
34
35
  if (unnecessary_kwarg = validate_kwargs(field))
35
36
  message = format(self.class::MSG, kwarg: unnecessary_kwarg)
36
37
  add_offense(node, message: message) do |corrector|
37
- kwarg_node = node.arguments.last.pairs.find do |pair|
38
+ kwarg_node = node.last_argument.pairs.find do |pair|
38
39
  pair.key.value == unnecessary_kwarg.to_sym
39
40
  end
40
41
  corrector.remove_preceding(kwarg_node, 2)
@@ -22,6 +22,7 @@ module RuboCop
22
22
  include RuboCop::GraphQL::NodePattern
23
23
 
24
24
  MSG = "Unnecessary field camelize"
25
+ RESTRICT_ON_SEND = %i[field].freeze
25
26
 
26
27
  def on_send(node)
27
28
  return unless field_definition?(node)
@@ -132,7 +132,7 @@ module RuboCop
132
132
 
133
133
  add_offense(node, message: message) do |corrector|
134
134
  if node.arguments?
135
- corrector.insert_after(arg_end(node.arguments.last), ", #{unresolved_args_source}")
135
+ corrector.insert_after(arg_end(node.last_argument), ", #{unresolved_args_source}")
136
136
  else
137
137
  corrector.insert_after(method_name(node), "(#{unresolved_args_source})")
138
138
  end
@@ -21,6 +21,7 @@ require_relative "graphql/resolver_method_length"
21
21
  require_relative "graphql/object_description"
22
22
  require_relative "graphql/ordered_arguments"
23
23
  require_relative "graphql/ordered_fields"
24
+ require_relative "graphql/prepare_method"
24
25
  require_relative "graphql/unused_argument"
25
26
  require_relative "graphql/unnecessary_argument_camelize"
26
27
  require_relative "graphql/unnecessary_field_alias"
@@ -12,7 +12,7 @@ module RuboCop
12
12
  (block
13
13
  (send nil? :argument ...)
14
14
  (args ...)
15
- $...
15
+ {(begin $...)|$...}
16
16
  )
17
17
  PATTERN
18
18
 
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "1.3.0".freeze
3
+ VERSION = "1.5.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Tsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-03 00:00:00.000000000 Z
11
+ date: 2024-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0.87'
61
+ version: '0.90'
62
62
  - - "<"
63
63
  - !ruby/object:Gem::Version
64
64
  version: '2'
@@ -68,7 +68,7 @@ dependencies:
68
68
  requirements:
69
69
  - - ">="
70
70
  - !ruby/object:Gem::Version
71
- version: '0.87'
71
+ version: '0.90'
72
72
  - - "<"
73
73
  - !ruby/object:Gem::Version
74
74
  version: '2'
@@ -104,6 +104,7 @@ files:
104
104
  - lib/rubocop/cop/graphql/object_description.rb
105
105
  - lib/rubocop/cop/graphql/ordered_arguments.rb
106
106
  - lib/rubocop/cop/graphql/ordered_fields.rb
107
+ - lib/rubocop/cop/graphql/prepare_method.rb
107
108
  - lib/rubocop/cop/graphql/resolver_method_length.rb
108
109
  - lib/rubocop/cop/graphql/unnecessary_argument_camelize.rb
109
110
  - lib/rubocop/cop/graphql/unnecessary_field_alias.rb