rubocop-graphql 0.1.3 → 0.2.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: 03b458539789cb0aeaf7e8852d2c7eba08554f7ef1d3621bce63d7cb271899be
4
- data.tar.gz: 16da0bb9da9cfdafd6da1d883890d8a96d6387519c7fba8cec883461d5d43130
3
+ metadata.gz: 97a32c7f3e6a945161380f4d71afe27ad379af7ed6f4657cea6b73d42dae5213
4
+ data.tar.gz: a039ae1c957f91d596f5b834035401ad031f2cf8723701e708d192f29dfb6784
5
5
  SHA512:
6
- metadata.gz: 12208cd27b2711fb499331e26e0eead2064115d1f7f47dadcbb0ae218ad8d28fd852a5f4a0f1e3bfcecac6302205612b88f57ae65af89735ab9c454b4e3fbc4f
7
- data.tar.gz: d3c8402557eb2b58f1c7a231d5b7a988d9bcfde59a8aa8b23c106f11cfe4ce6a193a1843165b296999bda3fbaa6d6f43560aff0082dd48ca6b18b0a0f5f3641c
6
+ metadata.gz: a17ab56af1141ef437dff2e908845c3c9a7d95b86f7e97c329787f43da0aef67be691a1d4179486d4580f40bb4fdbf423354ef619f7135651c0dcbe683a756b2
7
+ data.tar.gz: d9fb15417d019a952424942e5d860387da2bb1cd61abbeec1626ca9c7b9c2dec485cbe26b9cba28cec88128a828bb3cd1d776a9f3bc333bfc019d2ef8989b4e6
@@ -3,6 +3,16 @@ AllCops:
3
3
  Patterns:
4
4
  - "(?:^|/)graphql/"
5
5
 
6
+ GraphQL/ArgumentDescription:
7
+ Enabled: true
8
+ VersionAdded: '0.80'
9
+ Description: 'Ensures all arguments have a description'
10
+
11
+ GraphQL/ArgumentName:
12
+ Enabled: true
13
+ VersionAdded: '0.80'
14
+ Description: 'This cop checks whether argument names are snake_case'
15
+
6
16
  GraphQL/ResolverMethodLength:
7
17
  Enabled: true
8
18
  VersionAdded: '0.80'
@@ -29,3 +39,26 @@ GraphQL/FieldMethod:
29
39
  Enabled: true
30
40
  VersionAdded: '0.80'
31
41
  Description: 'Checks :method option is used for appropriate fields'
42
+
43
+ GraphQL/FieldName:
44
+ Enabled: true
45
+ VersionAdded: '0.80'
46
+ Description: 'This cop checks whether field names are snake_case'
47
+
48
+ GraphQL/ExtractInputType:
49
+ Enabled: true
50
+ VersionAdded: '0.80'
51
+ Description: 'Suggests using input type instead of many arguments'
52
+ MaxArguments: 2
53
+
54
+ GraphQL/ExtractType:
55
+ Enabled: true
56
+ VersionAdded: '0.80'
57
+ Description: 'Suggests extracting fields with common prefixes to the separate type'
58
+ MaxFields: 2
59
+ Prefixes:
60
+ - is
61
+ - with
62
+ - avg
63
+ - min
64
+ - max
@@ -2,13 +2,19 @@
2
2
 
3
3
  require "rubocop"
4
4
 
5
+ require_relative "rubocop/graphql/ext/snake_case"
6
+
5
7
  require_relative "rubocop/graphql"
6
8
  require_relative "rubocop/graphql/version"
7
9
  require_relative "rubocop/graphql/inject"
8
10
  require_relative "rubocop/graphql/node_pattern"
9
11
 
12
+ require_relative "rubocop/graphql/argument"
13
+ require_relative "rubocop/graphql/argument/block"
14
+ require_relative "rubocop/graphql/argument/kwargs"
10
15
  require_relative "rubocop/graphql/field"
11
- require_relative "rubocop/graphql/field_kwargs"
16
+ require_relative "rubocop/graphql/field/block"
17
+ require_relative "rubocop/graphql/field/kwargs"
12
18
  require_relative "rubocop/graphql/schema_member"
13
19
 
14
20
  RuboCop::GraphQL::Inject.defaults!
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ # This cop checks if each field has a description.
7
+ #
8
+ # @example
9
+ # # good
10
+ #
11
+ # class BanUser < BaseMutation
12
+ # argument :uuid, ID, required: true
13
+ # end
14
+ #
15
+ # # bad
16
+ #
17
+ # class BanUser < BaseMutation
18
+ # argument :uuid, ID, required: true, description: "UUID of the user to ban"
19
+ # end
20
+ #
21
+ class ArgumentDescription < Cop
22
+ include RuboCop::GraphQL::NodePattern
23
+
24
+ MSG = "Missing argument description"
25
+
26
+ def on_send(node)
27
+ return unless argument?(node)
28
+
29
+ argument = RuboCop::GraphQL::Argument.new(node)
30
+
31
+ add_offense(node) unless argument.description
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ # This cop checks whether field names are snake_case.
7
+ #
8
+ # @example
9
+ # # good
10
+ #
11
+ # class BanUser < BaseMutation
12
+ # argument :user_id, ID, required: true
13
+ # end
14
+ #
15
+ # # bad
16
+ #
17
+ # class BanUser < BaseMutation
18
+ # argument :userId, ID, required: true
19
+ # end
20
+ #
21
+ class ArgumentName < Cop
22
+ include RuboCop::GraphQL::NodePattern
23
+
24
+ using RuboCop::GraphQL::Ext::SnakeCase
25
+
26
+ MSG = "Use snake_case for argument names"
27
+
28
+ def on_send(node)
29
+ return unless argument?(node)
30
+
31
+ argument = RuboCop::GraphQL::Argument.new(node)
32
+ return if argument.name.snake_case?
33
+
34
+ add_offense(node)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ class ExtractInputType < Cop
7
+ # This cop checks fields on common prefix groups
8
+ #
9
+ # # @example
10
+ # # good
11
+ #
12
+ # class UpdateUser < BaseMutation
13
+ # argument :uuid, ID, required: true
14
+ # argument :user_attributes, UserAttributesInputType
15
+ # end
16
+ #
17
+ # # bad
18
+ #
19
+ # class UpdateUser < BaseMutation
20
+ # argument :uuid, ID, required: true
21
+ # argument :first_name, String, required: true
22
+ # argument :last_name, String, required: true
23
+ # end
24
+ #
25
+ include RuboCop::GraphQL::NodePattern
26
+
27
+ MSG = "Consider moving arguments to a new input type"
28
+
29
+ def on_class(node)
30
+ schema_member = RuboCop::GraphQL::SchemaMember.new(node)
31
+
32
+ if (body = schema_member.body)
33
+ arguments = body.select { |node| argument?(node) }
34
+
35
+ add_offense(arguments.last) if arguments.count > cop_config["MaxArguments"]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ class ExtractType < Cop
7
+ # This cop checks fields on common prefix groups
8
+ #
9
+ # # @example
10
+ # # good
11
+ #
12
+ # class Types::UserType < Types::BaseObject
13
+ # field :registered_at, String, null: false
14
+ # field :contact, Types::ContactType, null: false
15
+ #
16
+ # def contact
17
+ # self
18
+ # end
19
+ # end
20
+ #
21
+ # class Types::ContactType < Types::BaseObject
22
+ # field :phone, String, null: false
23
+ # field :first_name, String, null: false
24
+ # field :last_name, String, null: false
25
+ # end
26
+ #
27
+ # # bad
28
+ #
29
+ # class Types::UserType < Types::BaseObject
30
+ # field :registered_at, String, null: false
31
+ # field :contact_phone, String, null: false
32
+ # field :contact_first_name, String, null: false
33
+ # field :contact_last_name, String, null: false
34
+ # end
35
+ #
36
+ include RuboCop::GraphQL::NodePattern
37
+
38
+ def on_class(node)
39
+ schema_member = RuboCop::GraphQL::SchemaMember.new(node)
40
+
41
+ if (body = schema_member.body)
42
+ check_fields_prefixes(body)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ MSG = "Consider moving %<field_names>s to a new type and adding the `%<prefix>s` field instead"
49
+
50
+ def check_fields_prefixes(body)
51
+ sorted_prefixes = fractured(body).sort_by { |k, _| k.size }.reverse
52
+ already_offenced_fields = []
53
+
54
+ sorted_prefixes.each do |prefix, fields|
55
+ fields -= already_offenced_fields
56
+
57
+ next if fields.count < cop_config["MaxFields"]
58
+
59
+ add_offense(
60
+ fields.last.node,
61
+ message: message(prefix, fields.map(&:name).join(", "))
62
+ )
63
+
64
+ already_offenced_fields += fields
65
+ end
66
+ end
67
+
68
+ def fractured(body)
69
+ body.each_with_object({}) do |node, acc|
70
+ next unless field?(node)
71
+
72
+ field = RuboCop::GraphQL::Field.new(node)
73
+ next unless field.underscore_name.include?("_")
74
+
75
+ *prefixes, _ = field.underscore_name.split("_")
76
+
77
+ prefixes.each_with_object([]) do |prefix, prev_prefix|
78
+ prefix = (prev_prefix + [prefix]).join("_")
79
+ break if ignored_prefix?(prefix)
80
+
81
+ (acc[prefix] ||= []) << field
82
+
83
+ prev_prefix << prefix
84
+ end
85
+ end
86
+ end
87
+
88
+ def message(prefix, field_names)
89
+ format(MSG, field_names: field_names, prefix: prefix)
90
+ end
91
+
92
+ def ignored_prefix?(word)
93
+ cop_config["Prefixes"].include?(word)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -47,6 +47,7 @@ module RuboCop
47
47
  class FieldDefinitions < Cop
48
48
  include ConfigurableEnforcedStyle
49
49
  include RuboCop::GraphQL::NodePattern
50
+ include RuboCop::Cop::RangeHelp
50
51
 
51
52
  def_node_matcher :field_kwargs, <<~PATTERN
52
53
  (send nil? :field
@@ -74,12 +75,23 @@ module RuboCop
74
75
  end
75
76
  end
76
77
 
78
+ def autocorrect(node)
79
+ lambda do |corrector|
80
+ case style
81
+ when :define_resolver_after_definition
82
+ place_resolver_after_definitions(corrector, node)
83
+ when :group_definitions
84
+ group_field_declarations(corrector, node)
85
+ end
86
+ end
87
+ end
88
+
77
89
  private
78
90
 
79
91
  GROUP_DEFS_MSG = "Group all field definitions together."
80
92
 
81
93
  def check_grouped_field_declarations(body)
82
- fields = body.select { |node| field_definition?(node) || field_definition_with_body?(node) }
94
+ fields = body.select { |node| field?(node) }
83
95
 
84
96
  first_field = fields.first
85
97
 
@@ -90,6 +102,20 @@ module RuboCop
90
102
  end
91
103
  end
92
104
 
105
+ def group_field_declarations(corrector, node)
106
+ field = RuboCop::GraphQL::Field.new(node)
107
+
108
+ first_field = field.schema_member.body.find { |node|
109
+ field_definition?(node) || field_definition_with_body?(node)
110
+ }
111
+
112
+ source_to_insert = "\n" + indent(node) + node.source
113
+ corrector.insert_after(first_field.loc.expression, source_to_insert)
114
+
115
+ range = range_with_surrounding_space(range: node.loc.expression, side: :left)
116
+ corrector.remove(range)
117
+ end
118
+
93
119
  RESOLVER_AFTER_FIELD_MSG = "Define resolver method after field definition."
94
120
 
95
121
  def check_resolver_is_defined_after_definition(field)
@@ -108,6 +134,25 @@ module RuboCop
108
134
 
109
135
  add_offense(field.node, message: RESOLVER_AFTER_FIELD_MSG)
110
136
  end
137
+
138
+ def place_resolver_after_definitions(corrector, node)
139
+ field = RuboCop::GraphQL::Field.new(node)
140
+
141
+ method_definition = field.schema_member.find_method_definition(field.resolver_method_name)
142
+
143
+ field_definition = field_definition_with_body?(node.parent) ? node.parent : node
144
+
145
+ source_to_insert = indent(method_definition) + field_definition.source + "\n\n"
146
+ method_range = range_by_whole_lines(method_definition.loc.expression)
147
+ corrector.insert_before(method_range, source_to_insert)
148
+
149
+ range_to_remove = range_with_surrounding_space(range: field_definition.loc.expression, side: :left)
150
+ corrector.remove(range_to_remove)
151
+ end
152
+
153
+ def indent(node)
154
+ " " * node.location.column
155
+ end
111
156
  end
112
157
  end
113
158
  end
@@ -25,6 +25,7 @@ module RuboCop
25
25
  #
26
26
  class FieldMethod < Cop
27
27
  include RuboCop::GraphQL::NodePattern
28
+ include RuboCop::Cop::RangeHelp
28
29
 
29
30
  def_node_matcher :method_to_use, <<~PATTERN
30
31
  (def
@@ -42,12 +43,23 @@ module RuboCop
42
43
  return unless field_definition?(node)
43
44
 
44
45
  field = RuboCop::GraphQL::Field.new(node)
46
+ method_definition = suggest_method_name_for(field)
45
47
 
46
- method_name = field.resolver_method_name
47
- method_definition = field.schema_member.find_method_definition(method_name)
48
+ if (suggested_method_name = method_to_use(method_definition))
49
+ add_offense(node, message: message(suggested_method_name))
50
+ end
51
+ end
52
+
53
+ def autocorrect(node)
54
+ lambda do |corrector|
55
+ field = RuboCop::GraphQL::Field.new(node)
56
+ method_definition = suggest_method_name_for(field)
57
+ suggested_method_name = method_to_use(method_definition)
48
58
 
49
- if (method_name = method_to_use(method_definition))
50
- add_offense(node, message: message(method_name))
59
+ corrector.insert_after(node.loc.expression, ", method: :#{suggested_method_name}")
60
+
61
+ range = range_with_surrounding_space(range: method_definition.loc.expression, side: :left)
62
+ corrector.remove(range)
51
63
  end
52
64
  end
53
65
 
@@ -56,6 +68,11 @@ module RuboCop
56
68
  def message(method_name)
57
69
  format(MSG, method_name: method_name)
58
70
  end
71
+
72
+ def suggest_method_name_for(field)
73
+ method_name = field.resolver_method_name
74
+ field.schema_member.find_method_definition(method_name)
75
+ end
59
76
  end
60
77
  end
61
78
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module GraphQL
6
+ # This cop checks whether field names are snake_case.
7
+ #
8
+ # @example
9
+ # # good
10
+ #
11
+ # class UserType < BaseType
12
+ # field :first_name, String, null: true
13
+ # end
14
+ #
15
+ # # bad
16
+ #
17
+ # class UserType < BaseType
18
+ # field :firstName, String, null: true
19
+ # end
20
+ #
21
+ class FieldName < Cop
22
+ include RuboCop::GraphQL::NodePattern
23
+
24
+ using RuboCop::GraphQL::Ext::SnakeCase
25
+
26
+ MSG = "Use snake_case for field names"
27
+
28
+ def on_send(node)
29
+ return unless field_definition?(node)
30
+
31
+ field = RuboCop::GraphQL::Field.new(node)
32
+ return if field.name.snake_case?
33
+
34
+ add_offense(node)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,7 +2,12 @@
2
2
 
3
3
  require_relative "graphql/cop"
4
4
 
5
+ require_relative "graphql/argument_description"
6
+ require_relative "graphql/argument_name"
7
+ require_relative "graphql/extract_input_type"
8
+ require_relative "graphql/extract_type"
5
9
  require_relative "graphql/field_definitions"
6
10
  require_relative "graphql/field_description"
7
11
  require_relative "graphql/field_method"
12
+ require_relative "graphql/field_name"
8
13
  require_relative "graphql/resolver_method_length"
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ class Argument
6
+ extend RuboCop::NodePattern::Macros
7
+
8
+ def_node_matcher :argument_description, <<~PATTERN
9
+ (send nil? :argument _ _ (:str $_) ...)
10
+ PATTERN
11
+
12
+ def_node_matcher :argument_name, <<~PATTERN
13
+ (send nil? :argument (:sym $_) ...)
14
+ PATTERN
15
+
16
+ attr_reader :node
17
+
18
+ def initialize(node)
19
+ @node = node
20
+ end
21
+
22
+ def name
23
+ @name ||= argument_name(@node)
24
+ end
25
+
26
+ def description
27
+ @description ||= argument_description(@node) || kwargs.description || block.description
28
+ end
29
+
30
+ def kwargs
31
+ @kwargs ||= Argument::Kwargs.new(@node)
32
+ end
33
+
34
+ def block
35
+ @block ||= Argument::Block.new(@node.parent)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ class Argument
6
+ class Block
7
+ extend RuboCop::NodePattern::Macros
8
+
9
+ def_node_matcher :argument_block, <<~PATTERN
10
+ (block
11
+ (send nil? :argument ...)
12
+ (args)
13
+ $...
14
+ )
15
+ PATTERN
16
+
17
+ def_node_matcher :description_kwarg?, <<~PATTERN
18
+ (send nil? :description (str ...))
19
+ PATTERN
20
+
21
+ def initialize(argument_node)
22
+ @nodes = argument_block(argument_node) || []
23
+ end
24
+
25
+ def description
26
+ @nodes.find { |kwarg| description_kwarg?(kwarg) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ class Argument
6
+ class Kwargs
7
+ extend RuboCop::NodePattern::Macros
8
+
9
+ def_node_matcher :argument_kwargs, <<~PATTERN
10
+ (send nil? :argument
11
+ ...
12
+ (hash
13
+ $...
14
+ )
15
+ )
16
+ PATTERN
17
+
18
+ def_node_matcher :description_kwarg?, <<~PATTERN
19
+ (pair (sym :description) ...)
20
+ PATTERN
21
+
22
+ def initialize(argument_node)
23
+ @nodes = argument_kwargs(argument_node)
24
+ end
25
+
26
+ def description
27
+ @nodes.find { |kwarg| description_kwarg?(kwarg) }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ module Ext
6
+ module SnakeCase
7
+ SNAKE_CASE = /^[\da-z_]+[!?=]?$/
8
+
9
+ refine Symbol do
10
+ def snake_case?
11
+ match?(SNAKE_CASE)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -8,19 +8,15 @@ module RuboCop
8
8
 
9
9
  def_delegators :@node, :sibling_index, :parent
10
10
 
11
- def_node_matcher :field_kwargs, <<~PATTERN
12
- (send nil? :field
13
- ...
14
- (hash
15
- $...
16
- )
17
- )
18
- PATTERN
19
-
20
11
  def_node_matcher :field_name, <<~PATTERN
21
12
  (send nil? :field (:sym $_) ...)
22
13
  PATTERN
23
14
 
15
+ def_node_matcher :field_with_body_name, <<~PATTERN
16
+ (block
17
+ (send nil? :field (:sym $_) ...)...)
18
+ PATTERN
19
+
24
20
  def_node_matcher :field_description, <<~PATTERN
25
21
  (send nil? :field _ _ (:str $_) ...)
26
22
  PATTERN
@@ -32,11 +28,22 @@ module RuboCop
32
28
  end
33
29
 
34
30
  def name
35
- field_name(@node)
31
+ @name ||= field_name(@node) || field_with_body_name(@node)
32
+ end
33
+
34
+ def underscore_name
35
+ @underscore_name ||= begin
36
+ word = name.to_s.dup
37
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
38
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
39
+ word.tr!("-", "_")
40
+ word.downcase!
41
+ word
42
+ end
36
43
  end
37
44
 
38
45
  def description
39
- field_description(@node)
46
+ @description ||= field_description(@node) || kwargs.description || block.description
40
47
  end
41
48
 
42
49
  def resolver_method_name
@@ -44,7 +51,11 @@ module RuboCop
44
51
  end
45
52
 
46
53
  def kwargs
47
- @kwargs ||= FieldKwargs.new(field_kwargs(@node))
54
+ @kwargs ||= Field::Kwargs.new(@node)
55
+ end
56
+
57
+ def block
58
+ @block ||= Field::Block.new(@node.parent)
48
59
  end
49
60
 
50
61
  def schema_member
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ class Field
6
+ class Block
7
+ extend RuboCop::NodePattern::Macros
8
+
9
+ def_node_matcher :field_block, <<~PATTERN
10
+ (block
11
+ (send nil? :field ...)
12
+ (args)
13
+ $...
14
+ )
15
+ PATTERN
16
+
17
+ def_node_matcher :description_kwarg?, <<~PATTERN
18
+ (send nil? :description (str ...))
19
+ PATTERN
20
+
21
+ def initialize(field_node)
22
+ @nodes = field_block(field_node) || []
23
+ end
24
+
25
+ def description
26
+ @nodes.find { |kwarg| description_kwarg?(kwarg) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ class Field
6
+ class Kwargs
7
+ extend RuboCop::NodePattern::Macros
8
+
9
+ def_node_matcher :field_kwargs, <<~PATTERN
10
+ (send nil? :field
11
+ ...
12
+ (hash
13
+ $...
14
+ )
15
+ )
16
+ PATTERN
17
+
18
+ def_node_matcher :resolver_kwarg?, <<~PATTERN
19
+ (pair (sym :resolver) ...)
20
+ PATTERN
21
+
22
+ def_node_matcher :method_kwarg?, <<~PATTERN
23
+ (pair (sym :method) ...)
24
+ PATTERN
25
+
26
+ def_node_matcher :hash_key_kwarg?, <<~PATTERN
27
+ (pair (sym :hash_key) ...)
28
+ PATTERN
29
+
30
+ def_node_matcher :description_kwarg?, <<~PATTERN
31
+ (pair (sym :description) ...)
32
+ PATTERN
33
+
34
+ def_node_matcher :resolver_method_option, <<~PATTERN
35
+ (pair (sym :resolver_method) (sym $...))
36
+ PATTERN
37
+
38
+ def initialize(field_node)
39
+ @nodes = field_kwargs(field_node)
40
+ end
41
+
42
+ def resolver
43
+ @nodes.find { |kwarg| resolver_kwarg?(kwarg) }
44
+ end
45
+
46
+ def method
47
+ @nodes.find { |kwarg| method_kwarg?(kwarg) }
48
+ end
49
+
50
+ def hash_key
51
+ @nodes.find { |kwarg| hash_key_kwarg?(kwarg) }
52
+ end
53
+
54
+ def description
55
+ @nodes.find { |kwarg| description_kwarg?(kwarg) }
56
+ end
57
+
58
+ def resolver_method_name
59
+ @resolver_method_name ||= @nodes.flat_map { |kwarg| resolver_method_option(kwarg) }.compact.first
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -15,6 +15,14 @@ module RuboCop
15
15
  ...
16
16
  )
17
17
  PATTERN
18
+
19
+ def_node_matcher :argument?, <<~PATTERN
20
+ (send nil? :argument ...)
21
+ PATTERN
22
+
23
+ def field?(node)
24
+ field_definition?(node) || field_definition_with_body?(node)
25
+ end
18
26
  end
19
27
  end
20
28
  end
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "0.1.3"
3
+ VERSION = "0.2.0"
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.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Tsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-01 00:00:00.000000000 Z
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -77,15 +77,25 @@ files:
77
77
  - README.md
78
78
  - config/default.yml
79
79
  - lib/rubocop-graphql.rb
80
+ - lib/rubocop/cop/graphql/argument_description.rb
81
+ - lib/rubocop/cop/graphql/argument_name.rb
80
82
  - lib/rubocop/cop/graphql/cop.rb
83
+ - lib/rubocop/cop/graphql/extract_input_type.rb
84
+ - lib/rubocop/cop/graphql/extract_type.rb
81
85
  - lib/rubocop/cop/graphql/field_definitions.rb
82
86
  - lib/rubocop/cop/graphql/field_description.rb
83
87
  - lib/rubocop/cop/graphql/field_method.rb
88
+ - lib/rubocop/cop/graphql/field_name.rb
84
89
  - lib/rubocop/cop/graphql/resolver_method_length.rb
85
90
  - lib/rubocop/cop/graphql_cops.rb
86
91
  - lib/rubocop/graphql.rb
92
+ - lib/rubocop/graphql/argument.rb
93
+ - lib/rubocop/graphql/argument/block.rb
94
+ - lib/rubocop/graphql/argument/kwargs.rb
95
+ - lib/rubocop/graphql/ext/snake_case.rb
87
96
  - lib/rubocop/graphql/field.rb
88
- - lib/rubocop/graphql/field_kwargs.rb
97
+ - lib/rubocop/graphql/field/block.rb
98
+ - lib/rubocop/graphql/field/kwargs.rb
89
99
  - lib/rubocop/graphql/inject.rb
90
100
  - lib/rubocop/graphql/node_pattern.rb
91
101
  - lib/rubocop/graphql/schema_member.rb
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module GraphQL
5
- class FieldKwargs
6
- extend RuboCop::NodePattern::Macros
7
-
8
- def_node_matcher :resolver_kwarg?, <<~PATTERN
9
- (pair (sym :resolver) ...)
10
- PATTERN
11
-
12
- def_node_matcher :method_kwarg?, <<~PATTERN
13
- (pair (sym :method) ...)
14
- PATTERN
15
-
16
- def_node_matcher :hash_key_kwarg?, <<~PATTERN
17
- (pair (sym :hash_key) ...)
18
- PATTERN
19
-
20
- def_node_matcher :resolver_method_option, <<~PATTERN
21
- (pair (sym :resolver_method) (sym $...))
22
- PATTERN
23
-
24
- def initialize(nodes)
25
- @nodes = nodes
26
- end
27
-
28
- def resolver
29
- @nodes.find { |kwarg| resolver_kwarg?(kwarg) }
30
- end
31
-
32
- def method
33
- @nodes.find { |kwarg| method_kwarg?(kwarg) }
34
- end
35
-
36
- def hash_key
37
- @nodes.find { |kwarg| hash_key_kwarg?(kwarg) }
38
- end
39
-
40
- def resolver_method_name
41
- @resolver_method_name ||= @nodes.flat_map { |kwarg| resolver_method_option(kwarg) }.compact.first
42
- end
43
- end
44
- end
45
- end