rubocop-graphql 0.14.6 → 0.15.1

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: 7d6c5f9bf491004d53992e994ed1f1f1a4b71c8861678ac37aa477ccf56df8bd
4
+ data.tar.gz: 3e4d23b1d5b9037f5865007c417b4369331c3da3a45472253532b2307dcad154
5
5
  SHA512:
6
- metadata.gz: 9bdb7f16d1b31c795e8d624030e774c3c92ebb1481e4459f229fe135557eb072dbe2920c1cfc2600bb0d768756b338846da6db1b396def061d95ad4d0628e5b0
7
- data.tar.gz: d506eade963151227cfa3bf55f7ddf320b281111083ac784807c7c6aa6534a0899a01474d2c80f35c2460d1817b18f033d05ce880be59f477b5fe75cf85ce0e8
6
+ metadata.gz: 9de08df6e6bae9d0530fa7d05c521585b0017cc3c334c38c8975b7c4cf8dfc8f18b307ab4145311ba3d577ca0e2fc691938a6123e7b2d5436fb8892d8b1cf15f
7
+ data.tar.gz: 33c062e880965add9e25ab820e885bf2580c65041cee30ce1168a4e410cfece1af1bb0c3cadd7486ee98e67599f4ccc4b825e2f4bcae9996ee89924f47b14715
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
@@ -26,11 +26,6 @@ module RuboCop
26
26
 
27
27
  MSG = "Missing type description"
28
28
 
29
- # @!method has_i18n_description?(node)
30
- def_node_matcher :has_i18n_description?, <<~PATTERN
31
- (send nil? :description (send (const nil? :I18n) :t ...))
32
- PATTERN
33
-
34
29
  # @!method interface?(node)
35
30
  def_node_matcher :interface?, <<~PATTERN
36
31
  (send nil? :include (const ...))
@@ -53,8 +48,7 @@ module RuboCop
53
48
  private
54
49
 
55
50
  def has_description?(node)
56
- has_i18n_description?(node) ||
57
- description_method_call?(node)
51
+ description_method_call?(node)
58
52
  end
59
53
 
60
54
  def child_nodes(node)
@@ -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"
@@ -20,7 +20,7 @@ module RuboCop
20
20
  module DescriptionMethod
21
21
  extend RuboCop::NodePattern::Macros
22
22
 
23
- DESCRIPTION_STRING = "{({str|dstr|const} ...)|(send const ...)|(send ({str|dstr} ...) _)}"
23
+ DESCRIPTION_STRING = "{str|dstr|const|send}"
24
24
 
25
25
  # @!method description_method_call?(node)
26
26
  def_node_matcher :description_method_call?, <<~PATTERN
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "0.14.6".freeze
3
+ VERSION = "0.15.1".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.1
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-10-11 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: []