rubocop-graphql 0.11.3 → 0.12.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: ffc9fa90011bdaddbf2d485a5948ede1e7bf2ade1c91c3a960799a1e0cd47bb3
4
- data.tar.gz: 4dcbb755ed55538cfb8539b86f0c186e13b201bbfd0bbf3201d3091b8058c0fe
3
+ metadata.gz: 4a06d74f8fd3b057575ec841300332c5803de10df0fd2af2fb36f290830370e4
4
+ data.tar.gz: 75ecf04464efb37fd64dbc1f5ad4d2a2c12523a277090897a832080100530252
5
5
  SHA512:
6
- metadata.gz: 25cf86cd5e3e3942eafed3383df445c3f71296bc63a617ba4a0a9e597f6c355a1f5f94b1f2718439cd5606c50573758b8d3381a40af59937ba20cba150a9fe3d
7
- data.tar.gz: 745057b345ba218c88b5a21addced87fc6bd972147ac72281efa0e1c1db005694f3ec44d33dc6760bdff68edddf8fedaff1d23f270ca3fc5162b5f01652da902
6
+ metadata.gz: 14583dce74bc8bee2f10a024aad913f607de15b4e2ea340698b2b8ba211adaadd05e8130eb860074a94b670e967c8825b8bbbbd4b9d357bef99c201040531399
7
+ data.tar.gz: 48b9456d0f54573da9472832322dbdd11f5e7c4793a1713131fa4fc72d4f2e8e75b0206c22eb68a1a2bfc1811af3536464c6a1a2a23c0cd137108374035107c3
data/config/default.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  GraphQL:
2
+ Enabled: true
2
3
  Include:
3
4
  - "**/graphql/**/*"
4
5
  Exclude:
@@ -104,4 +105,8 @@ GraphQL/OrderedFields:
104
105
  VersionAdded: '0.80'
105
106
  Description: 'Fields should be alphabetically sorted within groups'
106
107
 
108
+ GraphQL/UnusedArgument:
109
+ Enabled: true
110
+ Description: 'Arguments should either be listed explicitly or **rest should be in the resolve signature'
111
+
107
112
 
@@ -24,19 +24,25 @@ module RuboCop
24
24
  "Argument `%<current>s` is duplicated%<field_name>s."
25
25
 
26
26
  def on_class(node)
27
- global_argument_names = Set.new
28
- argument_names_by_field = {}
27
+ return if nested_class?(node)
28
+
29
+ # { "MyClassName" => { "test_field" => <Set: {"field_arg_name"}> } }
30
+ argument_names_by_field_by_class = Hash.new do |h, k|
31
+ h[k] = Hash.new do |h1, k1|
32
+ h1[k1] = Set.new
33
+ end
34
+ end
29
35
 
30
36
  argument_declarations(node).each do |current|
31
37
  current_field_name = field_name(current)
32
38
  current_argument_name = argument_name(current)
39
+ class_name = current_class_name(current)
33
40
 
34
- if current_field_name
35
- argument_names_by_field[current_field_name] ||= Set.new
36
- argument_names = argument_names_by_field[current_field_name]
37
- else
38
- argument_names = global_argument_names
39
- end
41
+ argument_names = if current_field_name
42
+ argument_names_by_field_by_class[class_name][current_field_name]
43
+ else
44
+ argument_names_by_field_by_class[class_name][:root]
45
+ end
40
46
 
41
47
  unless argument_names.include?(current_argument_name)
42
48
  argument_names.add(current_argument_name)
@@ -49,6 +55,14 @@ module RuboCop
49
55
 
50
56
  private
51
57
 
58
+ def current_class_name(node)
59
+ node.each_ancestor(:class).first.defined_module_name
60
+ end
61
+
62
+ def nested_class?(node)
63
+ node.each_ancestor(:class).any?
64
+ end
65
+
52
66
  def register_offense(current)
53
67
  current_field_name = field_name(current)
54
68
  field_name_message = " in field `#{current_field_name}`" if current_field_name
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ # Arguments should either be listed explicitly or **rest should be in the resolve signature.
7
+ #
8
+ # @example
9
+ # # good
10
+ #
11
+ # class SomeResolver < Resolvers::Base
12
+ # argument :arg1, String, required: true
13
+ # argument :arg2, String, required: true
14
+ #
15
+ # def resolve(arg1:, arg2:); end
16
+ # end
17
+ #
18
+ # # good
19
+ #
20
+ # class SomeResolver < Resolvers::Base
21
+ # argument :arg1, String, required: true
22
+ # argument :arg2, String, required: true
23
+ #
24
+ # def resolve(arg1:, **rest); end
25
+ # end
26
+ #
27
+ # # good
28
+ #
29
+ # class SomeResolver < Resolvers::Base
30
+ # type SomeType, null: false
31
+ #
32
+ # argument :arg1, String, required: true
33
+ # argument :arg2, String, required: true
34
+ #
35
+ # def resolve(args); end
36
+ # end
37
+ #
38
+ # # bad
39
+ #
40
+ # class SomeResolver < Resolvers::Base
41
+ # type SomeType, null: false
42
+ #
43
+ # argument :arg1, String, required: true
44
+ # argument :arg2, String, required: true
45
+ #
46
+ # def resolve(arg1:); end
47
+ # end
48
+ #
49
+ # # bad
50
+ #
51
+ # class SomeResolver < Resolvers::Base
52
+ # type SomeType, null: false
53
+ #
54
+ # argument :arg1, String, required: true
55
+ # argument :arg2, String, required: true
56
+ #
57
+ # def resolve; end
58
+ # end
59
+ #
60
+ class UnusedArgument < Base
61
+ extend AutoCorrector
62
+
63
+ MSG = "Argument%<ending>s `%<unresolved_args>s` should be listed in the resolve signature."
64
+
65
+ def on_class(node)
66
+ resolve_method_node = find_resolve_method_node(node)
67
+ return if resolve_method_node.nil? ||
68
+ resolve_method_node.arguments.any? do |arg|
69
+ arg.arg_type? || arg.kwrestarg_type?
70
+ end
71
+
72
+ declared_arg_nodes = argument_declarations(node)
73
+ return unless declared_arg_nodes.any?
74
+
75
+ unresolved_args = find_unresolved_args(resolve_method_node, declared_arg_nodes)
76
+ register_offense(resolve_method_node, unresolved_args) if unresolved_args.any?
77
+ end
78
+
79
+ private
80
+
81
+ def find_resolve_method_node(node)
82
+ resolve_method_nodes = resolve_method_definition(node)
83
+ resolve_method_nodes.to_a.last if resolve_method_nodes.any?
84
+ end
85
+
86
+ def find_unresolved_args(method_node, declared_arg_nodes)
87
+ resolve_method_kwargs = method_node.arguments.select(&:kwarg_type?).map do |node|
88
+ node.node_parts[0]
89
+ end.to_set
90
+ declared_args = declared_arg_nodes.map { |node| RuboCop::GraphQL::Argument.new(node) }
91
+ declared_args.map(&:name).uniq.reject do |declared_arg|
92
+ resolve_method_kwargs.include?(declared_arg)
93
+ end
94
+ end
95
+
96
+ def register_offense(node, unresolved_args)
97
+ unresolved_args_source = unresolved_args.map { |v| "#{v}:" }.join(", ")
98
+
99
+ message = format(
100
+ self.class::MSG,
101
+ unresolved_args: unresolved_args_source,
102
+ ending: unresolved_args.size == 1 ? "" : "s"
103
+ )
104
+
105
+ add_offense(node, message: message) do |corrector|
106
+ if node.arguments?
107
+ corrector.insert_after(arg_end(node.arguments.last), ", #{unresolved_args_source}")
108
+ else
109
+ corrector.insert_after(method_name(node), "(#{unresolved_args_source})")
110
+ end
111
+ end
112
+ end
113
+
114
+ def method_name(node)
115
+ node.loc.keyword.end.resize(node.method_name.to_s.size + 1)
116
+ end
117
+
118
+ def arg_end(node)
119
+ node.loc.expression.end
120
+ end
121
+
122
+ def_node_search :argument_declarations, <<~PATTERN
123
+ (send nil? :argument (:sym _) ...)
124
+ PATTERN
125
+
126
+ def_node_search :resolve_method_definition, <<~PATTERN
127
+ (def :resolve
128
+ (args ...) ...)
129
+ PATTERN
130
+ end
131
+ end
132
+ end
133
+ end
@@ -16,3 +16,4 @@ require_relative "graphql/resolver_method_length"
16
16
  require_relative "graphql/object_description"
17
17
  require_relative "graphql/ordered_arguments"
18
18
  require_relative "graphql/ordered_fields"
19
+ require_relative "graphql/unused_argument"
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "0.11.3".freeze
3
+ VERSION = "0.12.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: 0.11.3
4
+ version: 0.12.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: 2021-12-22 00:00:00.000000000 Z
11
+ date: 2021-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,6 +100,7 @@ files:
100
100
  - lib/rubocop/cop/graphql/ordered_arguments.rb
101
101
  - lib/rubocop/cop/graphql/ordered_fields.rb
102
102
  - lib/rubocop/cop/graphql/resolver_method_length.rb
103
+ - lib/rubocop/cop/graphql/unused_argument.rb
103
104
  - lib/rubocop/cop/graphql_cops.rb
104
105
  - lib/rubocop/graphql.rb
105
106
  - lib/rubocop/graphql/argument.rb
@@ -121,7 +122,7 @@ licenses:
121
122
  metadata:
122
123
  homepage_uri: https://github.com/DmitryTsepelev/rubocop-graphql
123
124
  source_code_uri: https://github.com/DmitryTsepelev/rubocop-graphql
124
- changelog_uri: https://github.com/DmitryTsepelev/rubocop-graphql/CHANGELOG.md
125
+ changelog_uri: https://github.com/DmitryTsepelev/rubocop-graphql/blob/master/CHANGELOG.md
125
126
  post_install_message:
126
127
  rdoc_options: []
127
128
  require_paths: