rubocop-graphql 0.8.2 → 0.10.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: 22be8928aa9fbce1700f99d21ccddacd9590ab7bd6c6723e4b7458f974e02f66
4
- data.tar.gz: 6e06404047cba621b7493912723fa5eac13c19004d128339e494455758871831
3
+ metadata.gz: d7d2dac11533f09319d23f8770fe5b154c9477632a12d61f845a1c583e653635
4
+ data.tar.gz: 178ae678fdfc54ff8bc46af35160b5b0c0a57d183dff89045e3e790434c01728
5
5
  SHA512:
6
- metadata.gz: 94e9c24116f399d08b0c264e4b1b6c5dc50ac9436833fd8ec9f4916bdae102f5fdd5df5589a31502bca8aa65ccc61448a24b2e57aded363c35e6b0adec1513f6
7
- data.tar.gz: '0855eb683b91a3d5bb6e78b89c7c3089df5832813b1c298b26edf56de2e3c4ee71da837d279bad5ce15fd4dbcf9197fe908f81f77967a7b7345c9a1b3fdcb1f2'
6
+ metadata.gz: 0ea0e2358678578a7b6404c320fc836644fb6fd08cf33dfd13937eba0d991b2724fbd69b8ea9ff1f162ddc4c0b09f384c2344cbd4197e6744fef5931ea10a1da
7
+ data.tar.gz: bf5a8346e275f271c4a5c38cc9ad6c12b5271fa2ff3813853768a2f183530b078e214a7598cc00ebe43edefbfb2b2f79bfcd85a8d71ab664ed3fd43ddc7a87ea
data/config/default.yml CHANGED
@@ -48,6 +48,7 @@ GraphQL/FieldName:
48
48
  Enabled: true
49
49
  VersionAdded: '0.80'
50
50
  Description: 'This cop checks whether field names are snake_case'
51
+ SafeAutoCorrect: false
51
52
 
52
53
  GraphQL/ExtractInputType:
53
54
  Enabled: true
@@ -67,6 +68,11 @@ GraphQL/ExtractType:
67
68
  - min
68
69
  - max
69
70
 
71
+ GraphQL/LegacyDsl:
72
+ Enabled: true
73
+ VersionAdded: '0.80'
74
+ Description: 'Checks that types are defined with class-based API'
75
+
70
76
  GraphQL/ObjectDescription:
71
77
  Enabled: true
72
78
  VersionAdded: '0.80'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UnderscoreString
4
+ refine String do
5
+ # This method was extracted from activesupport in Rails:
6
+ # https://github.com/rails/rails/blob/8dab534ca81dd32c6a83ac03596a1feb7ddaaca7/activesupport/lib/active_support/inflector/methods.rb#L96
7
+
8
+ def underscore
9
+ camel_cased_word = self
10
+ regex = /(?:(?<=([A-Za-z\d]))|\b)((?=a)b)(?=\b|[^a-z])/
11
+ return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
12
+
13
+ word = camel_cased_word.to_s.gsub("::", "/")
14
+ word.gsub!(regex) { "#{Regexp.last_match(1) && '_'}#{Regexp.last_match(2).downcase}" }
15
+ word.gsub!(/([A-Z\d]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) do
16
+ (Regexp.last_match(1) || Regexp.last_match(2)) << "_"
17
+ end
18
+ word.tr!("-", "_")
19
+ word.downcase!
20
+ word
21
+ end
22
+ end
23
+ end
@@ -18,7 +18,7 @@ module RuboCop
18
18
  # argument :uuid, ID, required: true
19
19
  # end
20
20
  #
21
- class ArgumentDescription < Cop
21
+ class ArgumentDescription < Base
22
22
  include RuboCop::GraphQL::NodePattern
23
23
 
24
24
  MSG = "Missing argument description"
@@ -18,7 +18,7 @@ module RuboCop
18
18
  # argument :userId, ID, required: true
19
19
  # end
20
20
  #
21
- class ArgumentName < Cop
21
+ class ArgumentName < Base
22
22
  include RuboCop::GraphQL::NodePattern
23
23
 
24
24
  using RuboCop::GraphQL::Ext::SnakeCase
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module GraphQL
6
- class ExtractInputType < Cop
6
+ class ExtractInputType < Base
7
7
  # This cop checks fields on common prefix groups
8
8
  #
9
9
  # # @example
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module GraphQL
6
- class ExtractType < Cop
6
+ class ExtractType < Base
7
7
  # This cop checks fields on common prefix groups
8
8
  #
9
9
  # # @example
@@ -44,7 +44,8 @@ module RuboCop
44
44
  # object.contact_data.last_name
45
45
  # end
46
46
  # end
47
- class FieldDefinitions < Cop
47
+ class FieldDefinitions < Base
48
+ extend AutoCorrector
48
49
  include ConfigurableEnforcedStyle
49
50
  include RuboCop::GraphQL::NodePattern
50
51
  include RuboCop::Cop::RangeHelp
@@ -75,17 +76,6 @@ module RuboCop
75
76
  end
76
77
  end
77
78
 
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
-
89
79
  private
90
80
 
91
81
  GROUP_DEFS_MSG = "Group all field definitions together."
@@ -98,7 +88,9 @@ module RuboCop
98
88
  fields.each_with_index do |node, idx|
99
89
  next if node.sibling_index == first_field.sibling_index + idx
100
90
 
101
- add_offense(node, message: GROUP_DEFS_MSG)
91
+ add_offense(node, message: GROUP_DEFS_MSG) do |corrector|
92
+ group_field_declarations(corrector, node)
93
+ end
102
94
  end
103
95
  end
104
96
 
@@ -133,7 +125,9 @@ module RuboCop
133
125
 
134
126
  return if method_definition.sibling_index - field_sibling_index == 1
135
127
 
136
- add_offense(field.node, message: RESOLVER_AFTER_FIELD_MSG)
128
+ add_offense(field.node, message: RESOLVER_AFTER_FIELD_MSG) do |corrector|
129
+ place_resolver_after_definitions(corrector, field.node)
130
+ end
137
131
  end
138
132
 
139
133
  def place_resolver_after_definitions(corrector, node)
@@ -18,7 +18,7 @@ module RuboCop
18
18
  # field :name, String, null: true
19
19
  # end
20
20
  #
21
- class FieldDescription < Cop
21
+ class FieldDescription < Base
22
22
  include RuboCop::GraphQL::NodePattern
23
23
 
24
24
  MSG = "Missing field description"
@@ -23,7 +23,8 @@ module RuboCop
23
23
  # end
24
24
  # end
25
25
  #
26
- class FieldHashKey < Cop
26
+ class FieldHashKey < Base
27
+ extend AutoCorrector
27
28
  include RuboCop::GraphQL::NodePattern
28
29
  include RuboCop::Cop::RangeHelp
29
30
 
@@ -33,7 +34,7 @@ module RuboCop
33
34
  (args)
34
35
  (send
35
36
  (send nil? :object) :[]
36
- (_type $_)
37
+ ({sym str} $_)
37
38
  )
38
39
  )
39
40
  PATTERN
@@ -47,32 +48,32 @@ module RuboCop
47
48
  method_definition = resolver_method_definition_for(field)
48
49
 
49
50
  if (suggested_hash_key_name = hash_key_to_use(method_definition))
50
- add_offense(node, message: message(suggested_hash_key_name))
51
+ add_offense(node, message: message(suggested_hash_key_name)) do |corrector|
52
+ autocorrect(corrector, node)
53
+ end
51
54
  end
52
55
  end
53
56
 
54
- def autocorrect(node)
55
- lambda do |corrector|
56
- field = RuboCop::GraphQL::Field.new(node)
57
- method_definition = resolver_method_definition_for(field)
58
- suggested_hash_key_name = hash_key_to_use(method_definition)
57
+ private
59
58
 
60
- corrector.insert_after(
61
- node.loc.expression, ", hash_key: #{suggested_hash_key_name.inspect}"
62
- )
59
+ def message(hash_key)
60
+ format(MSG, hash_key: hash_key)
61
+ end
63
62
 
64
- range = range_with_surrounding_space(
65
- range: method_definition.loc.expression, side: :left
66
- )
63
+ def autocorrect(corrector, node)
64
+ field = RuboCop::GraphQL::Field.new(node)
65
+ method_definition = resolver_method_definition_for(field)
66
+ suggested_hash_key_name = hash_key_to_use(method_definition)
67
67
 
68
- corrector.remove(range)
69
- end
70
- end
68
+ corrector.insert_after(
69
+ node.loc.expression, ", hash_key: #{suggested_hash_key_name.inspect}"
70
+ )
71
71
 
72
- private
72
+ range = range_with_surrounding_space(
73
+ range: method_definition.loc.expression, side: :left
74
+ )
73
75
 
74
- def message(hash_key)
75
- format(MSG, hash_key: hash_key)
76
+ corrector.remove(range)
76
77
  end
77
78
 
78
79
  def resolver_method_definition_for(field)
@@ -23,7 +23,8 @@ module RuboCop
23
23
  # end
24
24
  # end
25
25
  #
26
- class FieldMethod < Cop
26
+ class FieldMethod < Base
27
+ extend AutoCorrector
27
28
  include RuboCop::GraphQL::NodePattern
28
29
  include RuboCop::Cop::RangeHelp
29
30
 
@@ -46,22 +47,9 @@ module RuboCop
46
47
  method_definition = suggest_method_name_for(field)
47
48
 
48
49
  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)
58
-
59
- corrector.insert_after(node.loc.expression, ", method: :#{suggested_method_name}")
60
-
61
- range = range_with_surrounding_space(
62
- range: method_definition.loc.expression, side: :left
63
- )
64
- corrector.remove(range)
50
+ add_offense(node, message: message(suggested_method_name)) do |corrector|
51
+ autocorrect(corrector, node)
52
+ end
65
53
  end
66
54
  end
67
55
 
@@ -71,6 +59,19 @@ module RuboCop
71
59
  format(MSG, method_name: method_name)
72
60
  end
73
61
 
62
+ def autocorrect(corrector, node)
63
+ field = RuboCop::GraphQL::Field.new(node)
64
+ method_definition = suggest_method_name_for(field)
65
+ suggested_method_name = method_to_use(method_definition)
66
+
67
+ corrector.insert_after(node.loc.expression, ", method: :#{suggested_method_name}")
68
+
69
+ range = range_with_surrounding_space(
70
+ range: method_definition.loc.expression, side: :left
71
+ )
72
+ corrector.remove(range)
73
+ end
74
+
74
75
  def suggest_method_name_for(field)
75
76
  method_name = field.resolver_method_name
76
77
  field.schema_member.find_method_definition(method_name)
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../../refinements/underscore_string"
4
+
5
+ using UnderscoreString unless String.method_defined?(:underscore)
6
+
3
7
  module RuboCop
4
8
  module Cop
5
9
  module GraphQL
@@ -18,7 +22,8 @@ module RuboCop
18
22
  # field :firstName, String, null: true
19
23
  # end
20
24
  #
21
- class FieldName < Cop
25
+ class FieldName < Base
26
+ extend AutoCorrector
22
27
  include RuboCop::GraphQL::NodePattern
23
28
 
24
29
  using RuboCop::GraphQL::Ext::SnakeCase
@@ -31,7 +36,17 @@ module RuboCop
31
36
  field = RuboCop::GraphQL::Field.new(node)
32
37
  return if field.name.snake_case?
33
38
 
34
- add_offense(node)
39
+ add_offense(node) do |corrector|
40
+ rename_field_name(corrector, field, node)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def rename_field_name(corrector, field, node)
47
+ name_field = field.name.to_s
48
+ new_line = node.source.sub(name_field, name_field.underscore)
49
+ corrector.replace(node, new_line)
35
50
  end
36
51
  end
37
52
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This cop checks whether type definitions are class-based or legacy.
6
+ #
7
+ # @example
8
+ # # good
9
+ #
10
+ # class Example < BaseType
11
+ # ....
12
+ # end
13
+ #
14
+ # # bad
15
+ #
16
+ # Example = GraphQL::ObjectType.define do
17
+ # ....
18
+ # ....
19
+ # end
20
+ #
21
+ module GraphQL
22
+ class LegacyDsl < Base
23
+ def_node_matcher :legacy_dsl?, <<~PATTERN
24
+ (block
25
+ (send
26
+ (const
27
+ (const nil? :GraphQL) _) :define)
28
+ ...
29
+ )
30
+ PATTERN
31
+
32
+ MSG = "Avoid using legacy based type-based definitions. Use class-based defintions instead."
33
+
34
+ def on_send(node)
35
+ return unless node.parent.type == :block
36
+
37
+ add_offense(node.parent) if legacy_dsl?(node.parent)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # # ...
21
21
  # end
22
22
  #
23
- class ObjectDescription < Cop
23
+ class ObjectDescription < Base
24
24
  include RuboCop::GraphQL::NodePattern
25
25
  include RuboCop::GraphQL::DescriptionMethod
26
26
 
@@ -48,15 +48,16 @@ module RuboCop
48
48
  # end
49
49
  # end
50
50
  #
51
- class OrderedArguments < Cop
51
+ class OrderedArguments < Base
52
+ extend AutoCorrector
53
+
54
+ include RuboCop::GraphQL::SwapRange
55
+
52
56
  MSG = "Arguments should be sorted in an alphabetical order within their section. " \
53
57
  "Field `%<current>s` should appear before `%<previous>s`."
54
58
 
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|
59
+ def on_class(node)
60
+ argument_declarations(node).each_cons(2) do |previous, current|
60
61
  next unless consecutive_lines(previous, current)
61
62
  next if argument_name(current) > argument_name(previous)
62
63
 
@@ -64,43 +65,18 @@ module RuboCop
64
65
  end
65
66
  end
66
67
 
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
68
  private
81
69
 
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
70
  def register_offense(previous, current)
98
71
  message = format(
99
72
  self.class::MSG,
100
73
  previous: argument_name(previous),
101
74
  current: argument_name(current)
102
75
  )
103
- add_offense(current, message: message)
76
+
77
+ add_offense(current, message: message) do |corrector|
78
+ swap_range(corrector, current, previous)
79
+ end
104
80
  end
105
81
 
106
82
  def argument_name(node)
@@ -30,33 +30,21 @@ module RuboCop
30
30
  # field :name, String, null: true
31
31
  # end
32
32
  #
33
- class OrderedFields < Cop
33
+ class OrderedFields < Base
34
+ extend AutoCorrector
35
+
36
+ include RuboCop::GraphQL::SwapRange
37
+
34
38
  MSG = "Fields should be sorted in an alphabetical order within their "\
35
39
  "section. "\
36
40
  "Field `%<current>s` should appear before `%<previous>s`."
37
41
 
38
- def investigate(processed_source)
39
- return if processed_source.blank?
40
-
41
- field_declarations(processed_source.ast)
42
- .each_cons(2) do |previous, current|
43
- next unless consecutive_lines(previous, current)
44
- next if field_name(current) > field_name(previous)
45
-
46
- register_offense(previous, current)
47
- end
48
- end
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)
42
+ def on_class(node)
43
+ field_declarations(node).each_cons(2) do |previous, current|
44
+ next unless consecutive_lines(previous, current)
45
+ next if field_name(current) > field_name(previous)
57
46
 
58
- lambda do |corrector|
59
- swap_range(corrector, current_range, previous_range)
47
+ register_offense(previous, current)
60
48
  end
61
49
  end
62
50
 
@@ -68,7 +56,10 @@ module RuboCop
68
56
  previous: field_name(previous),
69
57
  current: field_name(current)
70
58
  )
71
- add_offense(current, message: message)
59
+
60
+ add_offense(current, message: message) do |corrector|
61
+ swap_range(corrector, current, previous)
62
+ end
72
63
  end
73
64
 
74
65
  def field_name(node)
@@ -83,21 +74,6 @@ module RuboCop
83
74
  previous.source_range.last_line == current.source_range.first_line - 1
84
75
  end
85
76
 
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
-
101
77
  def_node_search :field_declarations, <<~PATTERN
102
78
  {
103
79
  (send nil? :field (:sym _) ...)
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # Comment lines can optionally be ignored.
8
8
  #
9
9
  # The maximum allowed length is configurable using the Max option.
10
- class ResolverMethodLength < Cop
10
+ class ResolverMethodLength < Base
11
11
  include RuboCop::Cop::ConfigurableMax
12
12
  include RuboCop::Cop::CodeLength
13
13
 
@@ -9,6 +9,7 @@ require_relative "graphql/field_description"
9
9
  require_relative "graphql/field_hash_key"
10
10
  require_relative "graphql/field_method"
11
11
  require_relative "graphql/field_name"
12
+ require_relative "graphql/legacy_dsl"
12
13
  require_relative "graphql/resolver_method_length"
13
14
  require_relative "graphql/object_description"
14
15
  require_relative "graphql/ordered_arguments"
@@ -20,7 +20,7 @@ module RuboCop
20
20
  PATTERN
21
21
 
22
22
  def initialize(argument_node)
23
- @nodes = argument_kwargs(argument_node)
23
+ @nodes = argument_kwargs(argument_node) || []
24
24
  end
25
25
 
26
26
  def description
@@ -11,7 +11,7 @@ module RuboCop
11
11
  (block
12
12
  (send nil? :field ...)
13
13
  (args)
14
- $...
14
+ {(begin $...)|$...}
15
15
  )
16
16
  PATTERN
17
17
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module GraphQL
5
+ module SwapRange
6
+ def swap_range(corrector, current, previous)
7
+ current_range = declaration(current)
8
+ previous_range = declaration(previous)
9
+
10
+ src1 = current_range.source
11
+ src2 = previous_range.source
12
+
13
+ corrector.replace(current_range, src2)
14
+ corrector.replace(previous_range, src1)
15
+ end
16
+
17
+ def declaration(node)
18
+ buffer = processed_source.buffer
19
+ begin_pos = node.source_range.begin_pos
20
+ end_line = buffer.line_for_position(node.loc.expression.end_pos)
21
+ end_pos = buffer.line_range(end_line).end_pos
22
+ Parser::Source::Range.new(buffer, begin_pos, end_pos)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module GraphQL
3
- VERSION = "0.8.2".freeze
3
+ VERSION = "0.10.2".freeze
4
4
  end
5
5
  end
@@ -9,6 +9,7 @@ require_relative "rubocop/graphql/version"
9
9
  require_relative "rubocop/graphql/inject"
10
10
  require_relative "rubocop/graphql/description_method"
11
11
  require_relative "rubocop/graphql/node_pattern"
12
+ require_relative "rubocop/graphql/swap_range"
12
13
 
13
14
  require_relative "rubocop/graphql/argument"
14
15
  require_relative "rubocop/graphql/argument/block"
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.8.2
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Tsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-23 00:00:00.000000000 Z
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - LICENSE.txt
83
83
  - README.md
84
84
  - config/default.yml
85
+ - lib/refinements/underscore_string.rb
85
86
  - lib/rubocop-graphql.rb
86
87
  - lib/rubocop/cop/graphql/argument_description.rb
87
88
  - lib/rubocop/cop/graphql/argument_name.rb
@@ -92,6 +93,7 @@ files:
92
93
  - lib/rubocop/cop/graphql/field_hash_key.rb
93
94
  - lib/rubocop/cop/graphql/field_method.rb
94
95
  - lib/rubocop/cop/graphql/field_name.rb
96
+ - lib/rubocop/cop/graphql/legacy_dsl.rb
95
97
  - lib/rubocop/cop/graphql/object_description.rb
96
98
  - lib/rubocop/cop/graphql/ordered_arguments.rb
97
99
  - lib/rubocop/cop/graphql/ordered_fields.rb
@@ -109,6 +111,7 @@ files:
109
111
  - lib/rubocop/graphql/inject.rb
110
112
  - lib/rubocop/graphql/node_pattern.rb
111
113
  - lib/rubocop/graphql/schema_member.rb
114
+ - lib/rubocop/graphql/swap_range.rb
112
115
  - lib/rubocop/graphql/version.rb
113
116
  homepage: https://github.com/DmitryTsepelev/rubocop-graphql
114
117
  licenses: