rubocop-graphql 0.6.1 → 0.8.2

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: 47871bc7644dbf0fb1f5c9b25af8d5f60183a8513d90f5a62d980b0fc865f9ad
4
- data.tar.gz: 18177a7497deef3c5342405b5b393eb5e1bae75cbf8e8eee5da636c814b51ea0
3
+ metadata.gz: 22be8928aa9fbce1700f99d21ccddacd9590ab7bd6c6723e4b7458f974e02f66
4
+ data.tar.gz: 6e06404047cba621b7493912723fa5eac13c19004d128339e494455758871831
5
5
  SHA512:
6
- metadata.gz: 7d2f3153652722d359d0ee0d5c6da8f9d03e1cae62c78e1e5f1b9fc577cfc361fd39cdfa0cd0addee6fb6c0e36b8c51bca485cc18f9c15fa3b1495d941668b0d
7
- data.tar.gz: bcb8a5d5938abd6b9be712f51a6363c31098d604dafcf725a8da6edff5d737c42532b329ba831d1d09277f78d340da9d105b58c37b0b494d5e526a882eda70b1
6
+ metadata.gz: 94e9c24116f399d08b0c264e4b1b6c5dc50ac9436833fd8ec9f4916bdae102f5fdd5df5589a31502bca8aa65ccc61448a24b2e57aded363c35e6b0adec1513f6
7
+ data.tar.gz: '0855eb683b91a3d5bb6e78b89c7c3089df5832813b1c298b26edf56de2e3c4ee71da837d279bad5ce15fd4dbcf9197fe908f81f77967a7b7345c9a1b3fdcb1f2'
data/config/default.yml CHANGED
@@ -1,7 +1,6 @@
1
- AllCops:
2
- GraphQL:
3
- Patterns:
4
- - "(?:^|/)graphql/"
1
+ GraphQL:
2
+ Include:
3
+ - "**/graphql/**/*"
5
4
 
6
5
  GraphQL/ArgumentDescription:
7
6
  Enabled: true
@@ -74,4 +73,4 @@ GraphQL/ObjectDescription:
74
73
  Description: 'Ensures all types have a description'
75
74
  Exclude:
76
75
  - '**/*_schema.rb'
77
- - '**/base_*.rb'
76
+ - '**/base_*.rb'
@@ -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"
@@ -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 _) ...)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "graphql/cop"
4
-
5
3
  require_relative "graphql/argument_description"
6
4
  require_relative "graphql/argument_name"
7
5
  require_relative "graphql/extract_input_type"
@@ -13,4 +11,5 @@ require_relative "graphql/field_method"
13
11
  require_relative "graphql/field_name"
14
12
  require_relative "graphql/resolver_method_length"
15
13
  require_relative "graphql/object_description"
14
+ require_relative "graphql/ordered_arguments"
16
15
  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.1".freeze
3
+ VERSION = "0.8.2".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.1
4
+ version: 0.8.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: 2020-10-30 00:00:00.000000000 Z
11
+ date: 2021-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,7 +85,6 @@ files:
85
85
  - lib/rubocop-graphql.rb
86
86
  - lib/rubocop/cop/graphql/argument_description.rb
87
87
  - lib/rubocop/cop/graphql/argument_name.rb
88
- - lib/rubocop/cop/graphql/cop.rb
89
88
  - lib/rubocop/cop/graphql/extract_input_type.rb
90
89
  - lib/rubocop/cop/graphql/extract_type.rb
91
90
  - lib/rubocop/cop/graphql/field_definitions.rb
@@ -94,6 +93,7 @@ files:
94
93
  - lib/rubocop/cop/graphql/field_method.rb
95
94
  - lib/rubocop/cop/graphql/field_name.rb
96
95
  - lib/rubocop/cop/graphql/object_description.rb
96
+ - lib/rubocop/cop/graphql/ordered_arguments.rb
97
97
  - lib/rubocop/cop/graphql/ordered_fields.rb
98
98
  - lib/rubocop/cop/graphql/resolver_method_length.rb
99
99
  - lib/rubocop/cop/graphql_cops.rb
@@ -101,6 +101,7 @@ files:
101
101
  - lib/rubocop/graphql/argument.rb
102
102
  - lib/rubocop/graphql/argument/block.rb
103
103
  - lib/rubocop/graphql/argument/kwargs.rb
104
+ - lib/rubocop/graphql/description_method.rb
104
105
  - lib/rubocop/graphql/ext/snake_case.rb
105
106
  - lib/rubocop/graphql/field.rb
106
107
  - lib/rubocop/graphql/field/block.rb
@@ -116,7 +117,7 @@ metadata:
116
117
  homepage_uri: https://github.com/DmitryTsepelev/rubocop-graphql
117
118
  source_code_uri: https://github.com/DmitryTsepelev/rubocop-graphql
118
119
  changelog_uri: https://github.com/DmitryTsepelev/rubocop-graphql/CHANGELOG.md
119
- post_install_message:
120
+ post_install_message:
120
121
  rdoc_options: []
121
122
  require_paths:
122
123
  - lib
@@ -124,15 +125,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
125
  requirements:
125
126
  - - ">="
126
127
  - !ruby/object:Gem::Version
127
- version: '2.4'
128
+ version: '2.5'
128
129
  required_rubygems_version: !ruby/object:Gem::Requirement
129
130
  requirements:
130
131
  - - ">="
131
132
  - !ruby/object:Gem::Version
132
133
  version: '0'
133
134
  requirements: []
134
- rubygems_version: 3.0.3
135
- signing_key:
135
+ rubygems_version: 3.1.2
136
+ signing_key:
136
137
  specification_version: 4
137
138
  summary: Automatic performance checking tool for Ruby code.
138
139
  test_files: []
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- # Inspied by https://github.com/rubocop-hq/rubocop-rspec/blob/3a2088f79737e2e8e0e21482783f7d61411bf021/lib/rubocop/cop/rspec/cop.rb
5
- module Cop
6
- WorkaroundGraphqlCop = Cop.dup
7
-
8
- # Clone of the the normal RuboCop::Cop::Cop class so we can rewrite
9
- # the inherited method without breaking functionality
10
- class WorkaroundGraphqlCop
11
- # Remove the Cop.inherited method to be a noop. Our RSpec::Cop
12
- # class will invoke the inherited hook instead
13
- class << self
14
- undef inherited
15
- def inherited(*); end
16
- end
17
-
18
- # Special case `Module#<` so that the rspec support rubocop exports
19
- # is compatible with our subclass
20
- def self.<(other)
21
- other.equal?(RuboCop::Cop::Cop) || super
22
- end
23
- end
24
- private_constant(:WorkaroundGraphqlCop)
25
-
26
- module GraphQL
27
- # @abstract parent class to graphql-ruby cops
28
- #
29
- # The criteria for whether rubocop-rspec analyzes a certain ruby file
30
- # is configured via `AllCops/GraphQL`. For example, if you want to
31
- # customize your project to scan all files within a `graph/` directory
32
- # then you could add this to your configuration:
33
- #
34
- # @example configuring analyzed paths
35
- #
36
- # AllCops:
37
- # GraphQL:
38
- # Patterns:
39
- # - '(?:^|/)graph/'
40
- class Cop < WorkaroundGraphqlCop
41
- DEFAULT_CONFIGURATION =
42
- RuboCop::GraphQL::CONFIG.fetch("AllCops").fetch("GraphQL")
43
-
44
- DEFAULT_PATTERN_RE = Regexp.union(
45
- DEFAULT_CONFIGURATION.fetch("Patterns")
46
- .map(&Regexp.public_method(:new))
47
- )
48
-
49
- # Invoke the original inherited hook so our cops are recognized
50
- def self.inherited(subclass)
51
- RuboCop::Cop::Cop.inherited(subclass)
52
- end
53
-
54
- def relevant_file?(file)
55
- relevant_rubocop_graphql_file?(file) && super
56
- end
57
-
58
- private
59
-
60
- def relevant_rubocop_graphql_file?(file)
61
- graphql_pattern =~ file
62
- end
63
-
64
- def graphql_pattern
65
- if rspec_graphql_config?
66
- Regexp.union(rspec_graphql_config.map(&Regexp.public_method(:new)))
67
- else
68
- DEFAULT_PATTERN_RE
69
- end
70
- end
71
-
72
- def all_cops_config
73
- config
74
- .for_all_cops
75
- end
76
-
77
- def rspec_graphql_config?
78
- return unless all_cops_config.key?("GraphQL")
79
-
80
- all_cops_config.fetch("GraphQL").key?("Patterns")
81
- end
82
-
83
- def rspec_graphql_config
84
- all_cops_config
85
- .fetch("GraphQL", DEFAULT_CONFIGURATION)
86
- .fetch("Patterns")
87
- end
88
- end
89
- end
90
- end
91
- end