rubocop-graphql 0.1.3 → 0.2.0

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