rubocop-graphql 0.13.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rubocop/cop/graphql/field_definitions.rb +84 -14
- data/lib/rubocop/cop/graphql/field_hash_key.rb +7 -4
- data/lib/rubocop/cop/graphql/field_method.rb +7 -4
- data/lib/rubocop/cop/graphql/object_description.rb +1 -1
- data/lib/rubocop/cop/graphql/unused_argument.rb +7 -4
- data/lib/rubocop/graphql/argument/block.rb +1 -1
- data/lib/rubocop/graphql/description_method.rb +9 -4
- data/lib/rubocop/graphql/field/block.rb +1 -1
- data/lib/rubocop/graphql/field.rb +12 -0
- data/lib/rubocop/graphql/heredoc.rb +23 -0
- data/lib/rubocop/graphql/sorbet.rb +30 -0
- data/lib/rubocop/graphql/version.rb +1 -1
- data/lib/rubocop-graphql.rb +2 -0
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8c5edb3e37ffc8245916608bb37f79dc28afb39dde464477e5b31e7f92aef59
|
4
|
+
data.tar.gz: 3fc868fb4e1ee8cdb0fed44c35ae98899e83eb605e0618faba161f65344554b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96f21cb69d2a7fc4c5c084e4859756fc7f525fc29e5c7c2dd4bf5fb1233d039ff3932d5783cdd10f91b0cee15c5cc8c91e94e3fec2f07ee0d09fdbc4b32e2799
|
7
|
+
data.tar.gz: c88d409a7c67630c3f68d98fb6d78418be4c3c99d601470f9732ed456b4ee86f3f2439323c019b82eaa52f2b613aa01fdf14cc195304eb3fc0a7c6bb3bec6774
|
@@ -44,11 +44,13 @@ module RuboCop
|
|
44
44
|
# object.contact_data.last_name
|
45
45
|
# end
|
46
46
|
# end
|
47
|
-
class FieldDefinitions < Base
|
47
|
+
class FieldDefinitions < Base # rubocop:disable Metrics/ClassLength
|
48
48
|
extend AutoCorrector
|
49
49
|
include ConfigurableEnforcedStyle
|
50
50
|
include RuboCop::GraphQL::NodePattern
|
51
51
|
include RuboCop::Cop::RangeHelp
|
52
|
+
include RuboCop::GraphQL::Sorbet
|
53
|
+
include RuboCop::GraphQL::Heredoc
|
52
54
|
|
53
55
|
def_node_matcher :field_kwargs, <<~PATTERN
|
54
56
|
(send nil? :field
|
@@ -101,14 +103,14 @@ module RuboCop
|
|
101
103
|
field_definition?(node) || field_definition_with_body?(node)
|
102
104
|
end
|
103
105
|
|
104
|
-
|
105
|
-
corrector.insert_after(first_field.loc.expression, source_to_insert)
|
106
|
+
insert_new_resolver(corrector, first_field, node)
|
106
107
|
|
107
|
-
|
108
|
-
corrector.remove(range)
|
108
|
+
remove_old_resolver(corrector, node)
|
109
109
|
end
|
110
110
|
|
111
111
|
RESOLVER_AFTER_FIELD_MSG = "Define resolver method after field definition."
|
112
|
+
RESOLVER_AFTER_LAST_FIELD_MSG = "Define resolver method after last field definition " \
|
113
|
+
"sharing resolver method."
|
112
114
|
|
113
115
|
def check_resolver_is_defined_after_definition(field)
|
114
116
|
return if field.kwargs.resolver || field.kwargs.method || field.kwargs.hash_key
|
@@ -116,6 +118,22 @@ module RuboCop
|
|
116
118
|
method_definition = field.schema_member.find_method_definition(field.resolver_method_name)
|
117
119
|
return unless method_definition
|
118
120
|
|
121
|
+
fields_with_same_resolver = fields_with_same_resolver(field, method_definition)
|
122
|
+
return unless field.name == fields_with_same_resolver.last.name
|
123
|
+
|
124
|
+
return if resolver_defined_after_definition?(field, method_definition)
|
125
|
+
|
126
|
+
add_offense(field.node,
|
127
|
+
message: offense_message(fields_with_same_resolver.one?)) do |corrector|
|
128
|
+
place_resolver_after_field_definition(corrector, field.node)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def offense_message(single_field_using_resolver)
|
133
|
+
single_field_using_resolver ? RESOLVER_AFTER_FIELD_MSG : RESOLVER_AFTER_LAST_FIELD_MSG
|
134
|
+
end
|
135
|
+
|
136
|
+
def resolver_defined_after_definition?(field, method_definition)
|
119
137
|
field_sibling_index =
|
120
138
|
if field_definition_with_body?(field.parent)
|
121
139
|
field.parent.sibling_index
|
@@ -123,28 +141,80 @@ module RuboCop
|
|
123
141
|
field.sibling_index
|
124
142
|
end
|
125
143
|
|
126
|
-
|
144
|
+
field_to_resolver_offset = method_definition.sibling_index - field_sibling_index
|
127
145
|
|
128
|
-
|
129
|
-
|
146
|
+
case field_to_resolver_offset
|
147
|
+
when 1 # resolver is immediately after field definition
|
148
|
+
return true
|
149
|
+
when 2 # there is a node between the field definition and its resolver
|
150
|
+
return true if has_sorbet_signature?(method_definition)
|
130
151
|
end
|
152
|
+
|
153
|
+
false
|
131
154
|
end
|
132
155
|
|
133
|
-
def
|
156
|
+
def fields_with_same_resolver(field, resolver)
|
157
|
+
fields = field.schema_member.body
|
158
|
+
.select { |node| field?(node) }
|
159
|
+
.map do |node|
|
160
|
+
field = field_definition_with_body?(node) ? node.children.first : node
|
161
|
+
RuboCop::GraphQL::Field.new(field)
|
162
|
+
end
|
163
|
+
|
164
|
+
[].tap do |fields_with_same_resolver|
|
165
|
+
fields.each do |field|
|
166
|
+
return [field] if field.name == resolver.method_name
|
167
|
+
next if field.kwargs.resolver_method_name != resolver.method_name
|
168
|
+
|
169
|
+
fields_with_same_resolver << field
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def place_resolver_after_field_definition(corrector, node)
|
134
175
|
field = RuboCop::GraphQL::Field.new(node)
|
135
176
|
|
136
|
-
|
177
|
+
resolver_method_name = field.resolver_method_name
|
178
|
+
resolver_definition = field.schema_member.find_method_definition(resolver_method_name)
|
137
179
|
|
138
180
|
field_definition = field_definition_with_body?(node.parent) ? node.parent : node
|
139
181
|
|
140
|
-
|
141
|
-
method_range = range_by_whole_lines(method_definition.loc.expression)
|
142
|
-
corrector.insert_before(method_range, source_to_insert)
|
182
|
+
insert_new_resolver(corrector, field_definition, resolver_definition)
|
143
183
|
|
184
|
+
remove_old_resolver(corrector, resolver_definition)
|
185
|
+
end
|
186
|
+
|
187
|
+
def insert_new_resolver(corrector, field_definition, resolver_definition)
|
188
|
+
source_to_insert =
|
189
|
+
"\n#{signature_to_insert(resolver_definition)}\n" \
|
190
|
+
"#{indent(resolver_definition)}#{resolver_definition.source}\n"
|
191
|
+
|
192
|
+
field_definition_range = range_including_heredoc(field_definition)
|
193
|
+
corrector.insert_after(field_definition_range, source_to_insert)
|
194
|
+
end
|
195
|
+
|
196
|
+
def remove_old_resolver(corrector, resolver_definition)
|
144
197
|
range_to_remove = range_with_surrounding_space(
|
145
|
-
range:
|
198
|
+
range: resolver_definition.loc.expression, side: :left
|
146
199
|
)
|
147
200
|
corrector.remove(range_to_remove)
|
201
|
+
|
202
|
+
resolver_signature = sorbet_signature_for(resolver_definition)
|
203
|
+
|
204
|
+
return unless resolver_signature
|
205
|
+
|
206
|
+
range_to_remove = range_with_surrounding_space(
|
207
|
+
range: resolver_signature.loc.expression, side: :left
|
208
|
+
)
|
209
|
+
corrector.remove(range_to_remove)
|
210
|
+
end
|
211
|
+
|
212
|
+
def signature_to_insert(node)
|
213
|
+
signature = sorbet_signature_for(node)
|
214
|
+
|
215
|
+
return unless signature
|
216
|
+
|
217
|
+
"\n#{indent(signature)}#{signature.source}"
|
148
218
|
end
|
149
219
|
|
150
220
|
def indent(node)
|
@@ -47,10 +47,13 @@ module RuboCop
|
|
47
47
|
field = RuboCop::GraphQL::Field.new(node)
|
48
48
|
method_definition = resolver_method_definition_for(field)
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
suggested_hash_key_name = hash_key_to_use(method_definition)
|
51
|
+
|
52
|
+
return if suggested_hash_key_name.nil?
|
53
|
+
return if RuboCop::GraphQL::Field::CONFLICT_FIELD_NAMES.include?(suggested_hash_key_name)
|
54
|
+
|
55
|
+
add_offense(node, message: message(suggested_hash_key_name)) do |corrector|
|
56
|
+
autocorrect(corrector, node)
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
@@ -46,10 +46,13 @@ module RuboCop
|
|
46
46
|
field = RuboCop::GraphQL::Field.new(node)
|
47
47
|
method_definition = suggest_method_name_for(field)
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
suggested_method_name = method_to_use(method_definition)
|
50
|
+
|
51
|
+
return if suggested_method_name.nil?
|
52
|
+
return if RuboCop::GraphQL::Field::CONFLICT_FIELD_NAMES.include?(suggested_method_name)
|
53
|
+
|
54
|
+
add_offense(node, message: message(suggested_method_name)) do |corrector|
|
55
|
+
autocorrect(corrector, node)
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
@@ -67,10 +67,7 @@ module RuboCop
|
|
67
67
|
|
68
68
|
def on_class(node)
|
69
69
|
resolve_method_node = find_resolve_method_node(node)
|
70
|
-
return if resolve_method_node.nil? ||
|
71
|
-
resolve_method_node.arguments.any? do |arg|
|
72
|
-
arg.arg_type? || arg.kwrestarg_type?
|
73
|
-
end
|
70
|
+
return if resolve_method_node.nil? || ignore_arguments_type?(resolve_method_node)
|
74
71
|
|
75
72
|
declared_arg_nodes = find_declared_arg_nodes(node)
|
76
73
|
return unless declared_arg_nodes.any?
|
@@ -109,6 +106,12 @@ module RuboCop
|
|
109
106
|
end
|
110
107
|
end
|
111
108
|
|
109
|
+
def ignore_arguments_type?(resolve_method_node)
|
110
|
+
resolve_method_node.arguments.any? do |arg|
|
111
|
+
arg.arg_type? || arg.kwrestarg_type? || arg.forward_arg_type?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
112
115
|
def register_offense(node, unresolved_args)
|
113
116
|
unresolved_args_source = unresolved_args.map { |v| "#{v}:" }.join(", ")
|
114
117
|
|
@@ -20,13 +20,18 @@ module RuboCop
|
|
20
20
|
module DescriptionMethod
|
21
21
|
extend RuboCop::NodePattern::Macros
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
DESCRIPTION_STRING = "{({str|dstr|const} ...)|(send const ...)|(send ({str|dstr} ...) _)}"
|
24
|
+
|
25
|
+
def_node_matcher :description_method_call?, <<~PATTERN
|
26
|
+
(send nil? :description #{DESCRIPTION_STRING})
|
27
|
+
PATTERN
|
28
|
+
|
29
|
+
def_node_matcher :description_with_block_arg?, <<~PATTERN
|
30
|
+
(send (lvar _) {:description= :description} #{DESCRIPTION_STRING})
|
26
31
|
PATTERN
|
27
32
|
|
28
33
|
def find_description_method(nodes)
|
29
|
-
nodes.find { |kwarg|
|
34
|
+
nodes.find { |kwarg| description_method_call?(kwarg) || description_with_block_arg?(kwarg) }
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
@@ -6,6 +6,18 @@ module RuboCop
|
|
6
6
|
extend Forwardable
|
7
7
|
extend RuboCop::NodePattern::Macros
|
8
8
|
|
9
|
+
# These constants were extracted from graphql-ruby in lib/graphql/schema/member/has_fields.rb
|
10
|
+
RUBY_KEYWORDS = %i[class module def undef begin rescue ensure end if unless then elsif else
|
11
|
+
case when while until for break next redo retry in do return yield super
|
12
|
+
self nil true false and or not alias defined? BEGIN END __LINE__
|
13
|
+
__FILE__].freeze
|
14
|
+
|
15
|
+
GRAPHQL_RUBY_KEYWORDS = %i[context object raw_value].freeze
|
16
|
+
|
17
|
+
CONFLICT_FIELD_NAMES = Set.new(
|
18
|
+
GRAPHQL_RUBY_KEYWORDS + RUBY_KEYWORDS + Object.instance_methods
|
19
|
+
)
|
20
|
+
|
9
21
|
def_delegators :@node, :sibling_index, :parent
|
10
22
|
|
11
23
|
def_node_matcher :field_name, <<~PATTERN
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module GraphQL
|
5
|
+
module Heredoc
|
6
|
+
def heredoc?(node)
|
7
|
+
(node.str_type? || node.dstr_type?) && node.heredoc?
|
8
|
+
end
|
9
|
+
|
10
|
+
def range_including_heredoc(node)
|
11
|
+
field = RuboCop::GraphQL::Field.new(node)
|
12
|
+
last_heredoc = field.kwargs.instance_variable_get(:@nodes).reverse.find do |kwarg|
|
13
|
+
heredoc?(kwarg.value)
|
14
|
+
end&.value
|
15
|
+
|
16
|
+
range = node.loc.expression
|
17
|
+
range = range.join(last_heredoc.loc.heredoc_end) if last_heredoc
|
18
|
+
|
19
|
+
range_by_whole_lines(range)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module GraphQL
|
5
|
+
module Sorbet
|
6
|
+
extend RuboCop::NodePattern::Macros
|
7
|
+
|
8
|
+
def_node_matcher(:sorbet_signature, <<~PATTERN)
|
9
|
+
(block (send nil? :sig) (args) ...)
|
10
|
+
PATTERN
|
11
|
+
|
12
|
+
def has_sorbet_signature?(node)
|
13
|
+
!!sorbet_signature_for(node)
|
14
|
+
end
|
15
|
+
|
16
|
+
def sorbet_signature_for(node)
|
17
|
+
node.parent.each_descendant.find do |sibling|
|
18
|
+
siblings_in_sequence?(sibling, node) &&
|
19
|
+
sorbet_signature(sibling)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def siblings_in_sequence?(first_node, second_node)
|
26
|
+
first_node.sibling_index - second_node.sibling_index == - 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/rubocop-graphql.rb
CHANGED
@@ -8,8 +8,10 @@ require_relative "rubocop/graphql"
|
|
8
8
|
require_relative "rubocop/graphql/version"
|
9
9
|
require_relative "rubocop/graphql/inject"
|
10
10
|
require_relative "rubocop/graphql/description_method"
|
11
|
+
require_relative "rubocop/graphql/heredoc"
|
11
12
|
require_relative "rubocop/graphql/node_pattern"
|
12
13
|
require_relative "rubocop/graphql/node_uniqueness"
|
14
|
+
require_relative "rubocop/graphql/sorbet"
|
13
15
|
require_relative "rubocop/graphql/swap_range"
|
14
16
|
|
15
17
|
require_relative "rubocop/graphql/argument"
|
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.
|
4
|
+
version: 0.14.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Tsepelev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -112,10 +112,12 @@ files:
|
|
112
112
|
- lib/rubocop/graphql/field.rb
|
113
113
|
- lib/rubocop/graphql/field/block.rb
|
114
114
|
- lib/rubocop/graphql/field/kwargs.rb
|
115
|
+
- lib/rubocop/graphql/heredoc.rb
|
115
116
|
- lib/rubocop/graphql/inject.rb
|
116
117
|
- lib/rubocop/graphql/node_pattern.rb
|
117
118
|
- lib/rubocop/graphql/node_uniqueness.rb
|
118
119
|
- lib/rubocop/graphql/schema_member.rb
|
120
|
+
- lib/rubocop/graphql/sorbet.rb
|
119
121
|
- lib/rubocop/graphql/swap_range.rb
|
120
122
|
- lib/rubocop/graphql/version.rb
|
121
123
|
homepage: https://github.com/DmitryTsepelev/rubocop-graphql
|
@@ -125,7 +127,7 @@ metadata:
|
|
125
127
|
homepage_uri: https://github.com/DmitryTsepelev/rubocop-graphql
|
126
128
|
source_code_uri: https://github.com/DmitryTsepelev/rubocop-graphql
|
127
129
|
changelog_uri: https://github.com/DmitryTsepelev/rubocop-graphql/blob/master/CHANGELOG.md
|
128
|
-
post_install_message:
|
130
|
+
post_install_message:
|
129
131
|
rdoc_options: []
|
130
132
|
require_paths:
|
131
133
|
- lib
|
@@ -140,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
142
|
- !ruby/object:Gem::Version
|
141
143
|
version: '0'
|
142
144
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
144
|
-
signing_key:
|
145
|
+
rubygems_version: 3.2.15
|
146
|
+
signing_key:
|
145
147
|
specification_version: 4
|
146
148
|
summary: Automatic performance checking tool for Ruby code.
|
147
149
|
test_files: []
|