rubocop-graphql 0.14.6 → 0.15.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: a7832bf74fe37877eee6544f83cc7625cfa874df93f6b141c07a2c1a628a927f
4
- data.tar.gz: c764f2caaf3cbbb685eb944b1a206c4904a484fe000f39a41c40b33846eecc1b
3
+ metadata.gz: 07b20077b6c0a6ec0ff0aa58528140efd701a90c3059c2483b213ea9039dfe35
4
+ data.tar.gz: 7f2e405ea2241a8f6d918577e75bfe523125700ed48441d434a1e671d1a93e56
5
5
  SHA512:
6
- metadata.gz: 9bdb7f16d1b31c795e8d624030e774c3c92ebb1481e4459f229fe135557eb072dbe2920c1cfc2600bb0d768756b338846da6db1b396def061d95ad4d0628e5b0
7
- data.tar.gz: d506eade963151227cfa3bf55f7ddf320b281111083ac784807c7c6aa6534a0899a01474d2c80f35c2460d1817b18f033d05ce880be59f477b5fe75cf85ce0e8
6
+ metadata.gz: 4ac7dc1b72346ef4f42d6739b1c0c9a10b35a80ab5b9421c937a3673d755384a15d06f5e358e88f1a4a29e426e7e2eea41e6e54634a76b8cf8dfeb34ea3a84ca
7
+ data.tar.gz: 68aa6accd90828a337828ba69f7e7d42bd5034644762cf83021a71352cfd3a8c7292934a3da2d30b1522a7055502ee49cd7c6ed7abcf6590a6a7b00062847eb7
data/config/default.yml CHANGED
@@ -38,6 +38,10 @@ GraphQL/FieldDefinitions:
38
38
  - group_definitions
39
39
  - define_resolver_after_definition
40
40
 
41
+ GraphQL/MultipleFieldDefinitions:
42
+ Enabled: true
43
+ Description: 'Ensures that fields with multiple definitions are grouped together'
44
+
41
45
  GraphQL/FieldDescription:
42
46
  Enabled: true
43
47
  VersionAdded: '0.80'
@@ -63,8 +63,9 @@ module RuboCop
63
63
  PATTERN
64
64
 
65
65
  def on_send(node)
66
- return if !field_definition?(node) || style != :define_resolver_after_definition
66
+ return if !field?(node) || style != :define_resolver_after_definition
67
67
 
68
+ node = node.parent if field_definition_with_body?(node.parent)
68
69
  field = RuboCop::GraphQL::Field.new(node)
69
70
  check_resolver_is_defined_after_definition(field)
70
71
  end
@@ -114,7 +115,10 @@ module RuboCop
114
115
  "sharing resolver method."
115
116
 
116
117
  def check_resolver_is_defined_after_definition(field)
117
- return if field.kwargs.resolver || field.kwargs.method || field.kwargs.hash_key
118
+ multiple_definitions = multiple_definitions(field)
119
+ return if field.node != multiple_definitions.last
120
+
121
+ return if field_has_no_resolver_method(field)
118
122
 
119
123
  method_definition = field.schema_member.find_method_definition(field.resolver_method_name)
120
124
  return unless method_definition
@@ -125,11 +129,25 @@ module RuboCop
125
129
  return if resolver_defined_after_definition?(field, method_definition)
126
130
 
127
131
  add_offense(field.node,
128
- message: offense_message(fields_with_same_resolver.one?)) do |corrector|
132
+ message: offense_message(
133
+ fields_with_same_resolver.one? && multiple_definitions.size == 1
134
+ )) do |corrector|
129
135
  place_resolver_after_field_definition(corrector, field.node)
130
136
  end
131
137
  end
132
138
 
139
+ def field_has_no_resolver_method(field)
140
+ field.kwargs.resolver || field.kwargs.method || field.kwargs.hash_key
141
+ end
142
+
143
+ def multiple_definitions(field)
144
+ field.schema_member.body.select { |node| field?(node) && field_name(node) == field.name }
145
+ end
146
+
147
+ def field_name(node)
148
+ RuboCop::GraphQL::Field.new(node).name
149
+ end
150
+
133
151
  def offense_message(single_field_using_resolver)
134
152
  single_field_using_resolver ? RESOLVER_AFTER_FIELD_MSG : RESOLVER_AFTER_LAST_FIELD_MSG
135
153
  end
@@ -157,10 +175,7 @@ module RuboCop
157
175
  def fields_with_same_resolver(field, resolver)
158
176
  fields = field.schema_member.body
159
177
  .select { |node| field?(node) }
160
- .map do |node|
161
- field = field_definition_with_body?(node) ? node.children.first : node
162
- RuboCop::GraphQL::Field.new(field)
163
- end
178
+ .map { |node| RuboCop::GraphQL::Field.new(node) }
164
179
 
165
180
  [].tap do |fields_with_same_resolver|
166
181
  fields.each do |field|
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ # Checks whether fields with multiple definitions are grouped together.
7
+ # @example
8
+ # # good
9
+ #
10
+ # class UserType < BaseType
11
+ # field :first_name, String, null: true
12
+ # field :first_name, Name, null: true
13
+ #
14
+ # def first_name
15
+ # object.contact_data.first_name
16
+ # end
17
+ # end
18
+ #
19
+ # # bad
20
+ #
21
+ # class UserType < BaseType
22
+ # field :first_name, String, null: true
23
+ #
24
+ # def first_name
25
+ # object.contact_data.first_name
26
+ # end
27
+ # field :first_name, Name, null: true
28
+ # end
29
+ class MultipleFieldDefinitions < Base
30
+ extend AutoCorrector
31
+ include RuboCop::GraphQL::NodePattern
32
+ include RuboCop::Cop::RangeHelp
33
+ include RuboCop::GraphQL::Heredoc
34
+
35
+ def on_send(node)
36
+ return unless field?(node)
37
+
38
+ node = node.parent if field_definition_with_body?(node.parent)
39
+
40
+ field = RuboCop::GraphQL::Field.new(node)
41
+
42
+ multiple_definitions = multiple_definitions(field)
43
+
44
+ return if multiple_definitions.size == 1 || node != multiple_definitions.last
45
+
46
+ if has_ungrouped_definitions?(multiple_definitions)
47
+ add_offense(node, message: MULTIPLE_DEFINITIONS_MSG) do |corrector|
48
+ group_multiple_definitions(corrector, multiple_definitions)
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ MULTIPLE_DEFINITIONS_MSG = "Group multiple field definitions together."
56
+
57
+ def multiple_definitions(field)
58
+ field.schema_member.body.select { |node| field?(node) && field_name(node) == field.name }
59
+ end
60
+
61
+ def field_name(node)
62
+ RuboCop::GraphQL::Field.new(node).name
63
+ end
64
+
65
+ def group_multiple_definitions(corrector, multiple_definitions)
66
+ multiple_definitions.each_cons(2) do |first, second|
67
+ next unless field_sibling_index(second) - field_sibling_index(first) > 1
68
+
69
+ insert_new_field(corrector, first, second)
70
+ remove_old_field(corrector, second)
71
+ end
72
+ end
73
+
74
+ def insert_new_field(corrector, first, second)
75
+ source_to_insert = "\n#{range_including_heredoc(second).source}"
76
+ field_definition_range = range_including_heredoc(first)
77
+ corrector.insert_after(field_definition_range, source_to_insert)
78
+ end
79
+
80
+ def remove_old_field(corrector, second)
81
+ range_to_remove = range_with_surrounding_space(
82
+ range: range_including_heredoc(second), side: :left
83
+ )
84
+ corrector.remove(range_to_remove)
85
+ end
86
+
87
+ def has_ungrouped_definitions?(multiple_definitions)
88
+ sibling_indices = multiple_definitions.map do |field|
89
+ field_sibling_index(field)
90
+ end
91
+
92
+ sibling_indices.each_cons(2).any? { |index1, index2| index2 - index1 > 1 }
93
+ end
94
+
95
+ def field_sibling_index(field)
96
+ if field_definition_with_body?(field.parent)
97
+ field.parent.sibling_index
98
+ else
99
+ field.sibling_index
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -12,6 +12,7 @@ require_relative "graphql/field_method"
12
12
  require_relative "graphql/field_name"
13
13
  require_relative "graphql/field_uniqueness"
14
14
  require_relative "graphql/legacy_dsl"
15
+ require_relative "graphql/multiple_field_definitions"
15
16
  require_relative "graphql/resolver_method_length"
16
17
  require_relative "graphql/object_description"
17
18
  require_relative "graphql/ordered_arguments"
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "0.14.6".freeze
3
+ VERSION = "0.15.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.14.6
4
+ version: 0.15.0
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-08-31 00:00:00.000000000 Z
11
+ date: 2022-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -96,6 +96,7 @@ files:
96
96
  - lib/rubocop/cop/graphql/field_name.rb
97
97
  - lib/rubocop/cop/graphql/field_uniqueness.rb
98
98
  - lib/rubocop/cop/graphql/legacy_dsl.rb
99
+ - lib/rubocop/cop/graphql/multiple_field_definitions.rb
99
100
  - lib/rubocop/cop/graphql/object_description.rb
100
101
  - lib/rubocop/cop/graphql/ordered_arguments.rb
101
102
  - lib/rubocop/cop/graphql/ordered_fields.rb
@@ -127,7 +128,7 @@ metadata:
127
128
  homepage_uri: https://github.com/DmitryTsepelev/rubocop-graphql
128
129
  source_code_uri: https://github.com/DmitryTsepelev/rubocop-graphql
129
130
  changelog_uri: https://github.com/DmitryTsepelev/rubocop-graphql/blob/master/CHANGELOG.md
130
- post_install_message:
131
+ post_install_message:
131
132
  rdoc_options: []
132
133
  require_paths:
133
134
  - lib
@@ -142,8 +143,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
143
  - !ruby/object:Gem::Version
143
144
  version: '0'
144
145
  requirements: []
145
- rubygems_version: 3.1.6
146
- signing_key:
146
+ rubygems_version: 3.3.7
147
+ signing_key:
147
148
  specification_version: 4
148
149
  summary: Automatic performance checking tool for Ruby code.
149
150
  test_files: []