rubocop-graphql 0.14.6 → 0.15.0

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 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: []