summaryrefslogtreecommitdiff
path: root/rubocop
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop')
-rw-r--r--rubocop/cop/graphql/resource_not_available_error.rb47
-rw-r--r--rubocop/node_pattern_helper.rb14
2 files changed, 61 insertions, 0 deletions
diff --git a/rubocop/cop/graphql/resource_not_available_error.rb b/rubocop/cop/graphql/resource_not_available_error.rb
new file mode 100644
index 00000000000..d759e145008
--- /dev/null
+++ b/rubocop/cop/graphql/resource_not_available_error.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require_relative '../../node_pattern_helper'
+
+module RuboCop
+ module Cop
+ module Graphql
+ # Encourages the use of `raise_resource_not_available_error!` method
+ # instead of `raise Gitlab::Graphql::Errors::ResourceNotAvailable`.
+ #
+ # @example
+ #
+ # # bad
+ # raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'message'
+ #
+ # # good
+ # raise_resource_not_available_error! 'message'
+ class ResourceNotAvailableError < Base
+ extend NodePatternHelper
+ extend AutoCorrector
+
+ MSG = 'Prefer using `raise_resource_not_available_error!` instead.'
+
+ EXCEPTION = 'Gitlab::Graphql::Errors::ResourceNotAvailable'
+
+ RESTRICT_ON_SEND = %i[raise].freeze
+
+ def_node_matcher :error, const_pattern(EXCEPTION)
+
+ def_node_matcher :raise_error, <<~PATTERN
+ (send nil? :raise #error $...)
+ PATTERN
+
+ def on_send(node)
+ raise_error(node) do |args|
+ add_offense(node) do |corrector|
+ replacement = +'raise_resource_not_available_error!'
+ replacement << " #{args.map(&:source).join(', ')}" if args.any?
+
+ corrector.replace(node, replacement)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/node_pattern_helper.rb b/rubocop/node_pattern_helper.rb
new file mode 100644
index 00000000000..ecd4560763c
--- /dev/null
+++ b/rubocop/node_pattern_helper.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module NodePatternHelper
+ # Returns a nested `(const ...)` node pattern for a full qualified +name+.
+ #
+ # @examples
+ # const_pattern 'Foo::Bar' # => (const (const {nil? cbase} :Foo) :Bar)
+ # const_pattern 'Foo::Bar', parent: ':Baz' # => (const (const :Baz :Foo) :Bar)
+ def const_pattern(name, parent: '{nil? cbase}')
+ name.split('::').inject(parent) { |memo, name_part| "(const #{memo} :#{name_part})" }
+ end
+ end
+end