rubocop-graphql 0.6.0 → 0.8.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: 5f19fb45c31f7313ff9617b4fbb5e34848123ec0a7e9e2c9b809f68e2555ffcc
4
- data.tar.gz: bd33d1bb602dc21f5732e5262a582ed0364d89f72138b48cef5ae01545f3acc5
3
+ metadata.gz: 62d96a424a721e274ada4265af5482248fd8786a07c9d533dadf368d39b0e142
4
+ data.tar.gz: b0e1877a97532a0190036b71c5068d95b3572a728b7eb2e2c51ee9b3c35869ce
5
5
  SHA512:
6
- metadata.gz: 721e3f6f4b686ae8fd51a741a1e9379d77098f7569cc6ac9143b4535dc344927f991af71ac104df47fd944a6d9e7cd204ed03c4e860d91f56ef6e9b3dc6f6d08
7
- data.tar.gz: 2d3179d6818fbabb4a1f1ed54676413db55215ea0f1c6fdc5645adf46943faa3dd2f86faca200736e8ed243b1d208d686b6ace8619c4174631078699d43f220f
6
+ metadata.gz: 7cbf14cb18196ed2ec0cbf75299f867674c2ac47a716f55b335cfb258377e4fd0d00968d51d28890fdb81d07211d2e4d6192efabf56bd349d0436c58c3c1e8e0
7
+ data.tar.gz: 4fb8ff31d9f3a500ed58118945c41451fa1178d3ace5635242861e176ec2fae4f1b31512dca2135d639a7d74e61d9c98d6fca4912fcd3609e033fc8241efba56
@@ -7,6 +7,7 @@ require_relative "rubocop/graphql/ext/snake_case"
7
7
  require_relative "rubocop/graphql"
8
8
  require_relative "rubocop/graphql/version"
9
9
  require_relative "rubocop/graphql/inject"
10
+ require_relative "rubocop/graphql/description_method"
10
11
  require_relative "rubocop/graphql/node_pattern"
11
12
 
12
13
  require_relative "rubocop/graphql/argument"
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # class will invoke the inherited hook instead
13
13
  class << self
14
14
  undef inherited
15
- def inherited(*); end
15
+ def inherited(*); end # rubocop:disable Lint/MissingSuper
16
16
  end
17
17
 
18
18
  # Special case `Module#<` so that the rspec support rubocop exports
@@ -47,7 +47,7 @@ module RuboCop
47
47
  )
48
48
 
49
49
  # Invoke the original inherited hook so our cops are recognized
50
- def self.inherited(subclass)
50
+ def self.inherited(subclass) # rubocop:disable Lint/MissingSuper
51
51
  RuboCop::Cop::Cop.inherited(subclass)
52
52
  end
53
53
 
@@ -32,7 +32,12 @@ module RuboCop
32
32
  if (body = schema_member.body)
33
33
  arguments = body.select { |node| argument?(node) }
34
34
 
35
- add_offense(arguments.last) if arguments.count > cop_config["MaxArguments"]
35
+ excess_arguments = arguments.count - cop_config["MaxArguments"]
36
+ return unless excess_arguments.positive?
37
+
38
+ arguments.last(excess_arguments).each do |excess_argument|
39
+ add_offense(excess_argument)
40
+ end
36
41
  end
37
42
  end
38
43
  end
@@ -109,7 +109,7 @@ module RuboCop
109
109
  field_definition?(node) || field_definition_with_body?(node)
110
110
  end
111
111
 
112
- source_to_insert = "\n" + indent(node) + node.source
112
+ source_to_insert = "\n#{indent(node)}#{node.source}"
113
113
  corrector.insert_after(first_field.loc.expression, source_to_insert)
114
114
 
115
115
  range = range_with_surrounding_space(range: node.loc.expression, side: :left)
@@ -143,7 +143,7 @@ module RuboCop
143
143
 
144
144
  field_definition = field_definition_with_body?(node.parent) ? node.parent : node
145
145
 
146
- source_to_insert = indent(method_definition) + field_definition.source + "\n\n"
146
+ source_to_insert = "#{indent(method_definition)}#{field_definition.source}\n\n"
147
147
  method_range = range_by_whole_lines(method_definition.loc.expression)
148
148
  corrector.insert_before(method_range, source_to_insert)
149
149
 
@@ -22,6 +22,7 @@ module RuboCop
22
22
  #
23
23
  class ObjectDescription < Cop
24
24
  include RuboCop::GraphQL::NodePattern
25
+ include RuboCop::GraphQL::DescriptionMethod
25
26
 
26
27
  MSG = "Missing type description"
27
28
 
@@ -29,10 +30,6 @@ module RuboCop
29
30
  (send nil? :description (send (const nil? :I18n) :t ...))
30
31
  PATTERN
31
32
 
32
- def_node_matcher :has_string_description?, <<~PATTERN
33
- (send nil? :description (:str $_))
34
- PATTERN
35
-
36
33
  def_node_matcher :interface?, <<~PATTERN
37
34
  (send nil? :include (const ...))
38
35
  PATTERN
@@ -54,7 +51,8 @@ module RuboCop
54
51
  private
55
52
 
56
53
  def has_description?(node)
57
- has_i18n_description?(node) || has_string_description?(node)
54
+ has_i18n_description?(node) ||
55
+ description_kwarg?(node)
58
56
  end
59
57
 
60
58
  def child_nodes(node)
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ # Arguments should be alphabetically sorted within groups.
7
+ #
8
+ # @example
9
+ # # good
10
+ #
11
+ # class UpdateProfile < BaseMutation
12
+ # argument :email, String, required: false
13
+ # argument :name, String, required: false
14
+ # end
15
+ #
16
+ # # good
17
+ #
18
+ # class UpdateProfile < BaseMutation
19
+ # argument :uuid, ID, required: true
20
+ #
21
+ # argument :email, String, required: false
22
+ # argument :name, String, required: false
23
+ # end
24
+ #
25
+ # # good
26
+ #
27
+ # class UserType < BaseType
28
+ # field :posts, PostType do
29
+ # argument :created_after, ISO8601DateTime, required: false
30
+ # argument :created_before, ISO8601DateTime, required: false
31
+ # end
32
+ # end
33
+ #
34
+ # # bad
35
+ #
36
+ # class UpdateProfile < BaseMutation
37
+ # argument :uuid, ID, required: true
38
+ # argument :name, String, required: false
39
+ # argument :email, String, required: false
40
+ # end
41
+ #
42
+ # # bad
43
+ #
44
+ # class UserType < BaseType
45
+ # field :posts, PostType do
46
+ # argument :created_before, ISO8601DateTime, required: false
47
+ # argument :created_after, ISO8601DateTime, required: false
48
+ # end
49
+ # end
50
+ #
51
+ class OrderedArguments < Cop
52
+ MSG = "Arguments should be sorted in an alphabetical order within their section. " \
53
+ "Field `%<current>s` should appear before `%<previous>s`."
54
+
55
+ def investigate(processed_source)
56
+ return if processed_source.blank?
57
+
58
+ argument_declarations(processed_source.ast)
59
+ .each_cons(2) do |previous, current|
60
+ next unless consecutive_lines(previous, current)
61
+ next if argument_name(current) > argument_name(previous)
62
+
63
+ register_offense(previous, current)
64
+ end
65
+ end
66
+
67
+ def autocorrect(node)
68
+ declarations = argument_declarations(processed_source.ast)
69
+ node_index = declarations.map(&:location).find_index(node.location)
70
+ previous_declaration = declarations.to_a[node_index - 1]
71
+
72
+ current_range = declaration(node)
73
+ previous_range = declaration(previous_declaration)
74
+
75
+ lambda do |corrector|
76
+ swap_range(corrector, current_range, previous_range)
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def declaration(node)
83
+ buffer = processed_source.buffer
84
+ begin_pos = node.source_range.begin_pos
85
+ end_line = buffer.line_for_position(node.loc.expression.end_pos)
86
+ end_pos = buffer.line_range(end_line).end_pos
87
+ Parser::Source::Range.new(buffer, begin_pos, end_pos)
88
+ end
89
+
90
+ def swap_range(corrector, range1, range2)
91
+ src1 = range1.source
92
+ src2 = range2.source
93
+ corrector.replace(range1, src2)
94
+ corrector.replace(range2, src1)
95
+ end
96
+
97
+ def register_offense(previous, current)
98
+ message = format(
99
+ self.class::MSG,
100
+ previous: argument_name(previous),
101
+ current: argument_name(current)
102
+ )
103
+ add_offense(current, message: message)
104
+ end
105
+
106
+ def argument_name(node)
107
+ node.first_argument.value.to_s
108
+ end
109
+
110
+ def consecutive_lines(previous, current)
111
+ previous.source_range.last_line == current.source_range.first_line - 1
112
+ end
113
+
114
+ def_node_search :argument_declarations, <<~PATTERN
115
+ (send nil? :argument (:sym _) ...)
116
+ PATTERN
117
+ end
118
+ end
119
+ end
120
+ end
@@ -47,6 +47,19 @@ module RuboCop
47
47
  end
48
48
  end
49
49
 
50
+ def autocorrect(node)
51
+ declarations = field_declarations(processed_source.ast)
52
+ node_index = declarations.map(&:location).find_index(node.location)
53
+ previous_declaration = declarations.to_a[node_index - 1]
54
+
55
+ current_range = declaration(node)
56
+ previous_range = declaration(previous_declaration)
57
+
58
+ lambda do |corrector|
59
+ swap_range(corrector, current_range, previous_range)
60
+ end
61
+ end
62
+
50
63
  private
51
64
 
52
65
  def register_offense(previous, current)
@@ -70,6 +83,21 @@ module RuboCop
70
83
  previous.source_range.last_line == current.source_range.first_line - 1
71
84
  end
72
85
 
86
+ def declaration(node)
87
+ buffer = processed_source.buffer
88
+ begin_pos = node.source_range.begin_pos
89
+ end_line = buffer.line_for_position(node.loc.expression.end_pos)
90
+ end_pos = buffer.line_range(end_line).end_pos
91
+ Parser::Source::Range.new(buffer, begin_pos, end_pos)
92
+ end
93
+
94
+ def swap_range(corrector, range1, range2)
95
+ src1 = range1.source
96
+ src2 = range2.source
97
+ corrector.replace(range1, src2)
98
+ corrector.replace(range2, src1)
99
+ end
100
+
73
101
  def_node_search :field_declarations, <<~PATTERN
74
102
  {
75
103
  (send nil? :field (:sym _) ...)
@@ -13,4 +13,5 @@ require_relative "graphql/field_method"
13
13
  require_relative "graphql/field_name"
14
14
  require_relative "graphql/resolver_method_length"
15
15
  require_relative "graphql/object_description"
16
+ require_relative "graphql/ordered_arguments"
16
17
  require_relative "graphql/ordered_fields"
@@ -5,6 +5,7 @@ module RuboCop
5
5
  class Argument
6
6
  class Block
7
7
  extend RuboCop::NodePattern::Macros
8
+ include DescriptionMethod
8
9
 
9
10
  def_node_matcher :argument_block, <<~PATTERN
10
11
  (block
@@ -14,16 +15,12 @@ module RuboCop
14
15
  )
15
16
  PATTERN
16
17
 
17
- def_node_matcher :description_kwarg?, <<~PATTERN
18
- (send nil? :description (str ...))
19
- PATTERN
20
-
21
18
  def initialize(argument_node)
22
19
  @nodes = argument_block(argument_node) || []
23
20
  end
24
21
 
25
22
  def description
26
- @nodes.find { |kwarg| description_kwarg?(kwarg) }
23
+ find_description_method(@nodes)
27
24
  end
28
25
  end
29
26
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ # Matches a variety of description formats commonly seen in Rails applications
6
+ #
7
+ # description 'blah'
8
+ #
9
+ # description "blah"
10
+ #
11
+ # description <<~EOT
12
+ # blah
13
+ # bloop
14
+ # EOT
15
+ #
16
+ # description <<-EOT.squish
17
+ # blah
18
+ # bloop
19
+ # EOT
20
+ module DescriptionMethod
21
+ extend RuboCop::NodePattern::Macros
22
+
23
+ def_node_matcher :description_kwarg?, <<~PATTERN
24
+ (send nil? :description {({str|dstr} ...)|(send ({str|dstr} ...) _)})
25
+ PATTERN
26
+
27
+ def find_description_method(nodes)
28
+ nodes.find { |kwarg| description_kwarg?(kwarg) }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -5,6 +5,7 @@ module RuboCop
5
5
  class Field
6
6
  class Block
7
7
  extend RuboCop::NodePattern::Macros
8
+ include DescriptionMethod
8
9
 
9
10
  def_node_matcher :field_block, <<~PATTERN
10
11
  (block
@@ -14,16 +15,12 @@ module RuboCop
14
15
  )
15
16
  PATTERN
16
17
 
17
- def_node_matcher :description_kwarg?, <<~PATTERN
18
- (send nil? :description (str ...))
19
- PATTERN
20
-
21
18
  def initialize(field_node)
22
19
  @nodes = field_block(field_node) || []
23
20
  end
24
21
 
25
22
  def description
26
- @nodes.find { |kwarg| description_kwarg?(kwarg) }
23
+ find_description_method(@nodes)
27
24
  end
28
25
  end
29
26
  end
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "0.6.0".freeze
3
+ VERSION = "0.8.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.6.0
4
+ version: 0.8.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: 2020-10-22 00:00:00.000000000 Z
11
+ date: 2021-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -61,7 +61,7 @@ dependencies:
61
61
  version: '0.87'
62
62
  - - "<"
63
63
  - !ruby/object:Gem::Version
64
- version: '1.1'
64
+ version: '2'
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
@@ -71,7 +71,7 @@ dependencies:
71
71
  version: '0.87'
72
72
  - - "<"
73
73
  - !ruby/object:Gem::Version
74
- version: '1.1'
74
+ version: '2'
75
75
  description: A collection of RuboCop cops to improve GraphQL-related code
76
76
  email:
77
77
  - dmitry.a.tsepelev@gmail.com
@@ -94,6 +94,7 @@ files:
94
94
  - lib/rubocop/cop/graphql/field_method.rb
95
95
  - lib/rubocop/cop/graphql/field_name.rb
96
96
  - lib/rubocop/cop/graphql/object_description.rb
97
+ - lib/rubocop/cop/graphql/ordered_arguments.rb
97
98
  - lib/rubocop/cop/graphql/ordered_fields.rb
98
99
  - lib/rubocop/cop/graphql/resolver_method_length.rb
99
100
  - lib/rubocop/cop/graphql_cops.rb
@@ -101,6 +102,7 @@ files:
101
102
  - lib/rubocop/graphql/argument.rb
102
103
  - lib/rubocop/graphql/argument/block.rb
103
104
  - lib/rubocop/graphql/argument/kwargs.rb
105
+ - lib/rubocop/graphql/description_method.rb
104
106
  - lib/rubocop/graphql/ext/snake_case.rb
105
107
  - lib/rubocop/graphql/field.rb
106
108
  - lib/rubocop/graphql/field/block.rb
@@ -116,7 +118,7 @@ metadata:
116
118
  homepage_uri: https://github.com/DmitryTsepelev/rubocop-graphql
117
119
  source_code_uri: https://github.com/DmitryTsepelev/rubocop-graphql
118
120
  changelog_uri: https://github.com/DmitryTsepelev/rubocop-graphql/CHANGELOG.md
119
- post_install_message:
121
+ post_install_message:
120
122
  rdoc_options: []
121
123
  require_paths:
122
124
  - lib
@@ -131,8 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
133
  - !ruby/object:Gem::Version
132
134
  version: '0'
133
135
  requirements: []
134
- rubygems_version: 3.0.3
135
- signing_key:
136
+ rubygems_version: 3.1.2
137
+ signing_key:
136
138
  specification_version: 4
137
139
  summary: Automatic performance checking tool for Ruby code.
138
140
  test_files: []