Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop/cop/lint/last_keyword_argument.rb')
-rw-r--r--rubocop/cop/lint/last_keyword_argument.rb71
1 files changed, 71 insertions, 0 deletions
diff --git a/rubocop/cop/lint/last_keyword_argument.rb b/rubocop/cop/lint/last_keyword_argument.rb
new file mode 100644
index 00000000000..430ea66e9a1
--- /dev/null
+++ b/rubocop/cop/lint/last_keyword_argument.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Lint
+ # This cop only works if there are files from deprecation_toolkit. You can
+ # generate these files by:
+ #
+ # 1. Running specs with RECORD_DEPRECATIONS=1
+ # 1. Downloading the complete set of deprecations/ files from a CI
+ # pipeline (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47720)
+ class LastKeywordArgument < Cop
+ MSG = 'Using the last argument as keyword parameters is deprecated'.freeze
+
+ DEPRECATIONS_GLOB = File.expand_path('../../../deprecations/**/*.yml', __dir__)
+ KEYWORD_DEPRECATION_STR = 'maybe ** should be added to the call'
+
+ def on_send(node)
+ arg = node.arguments.last
+ return unless arg
+
+ return unless known_match?(processed_source.file_path, node.first_line, node.method_name.to_s)
+
+ return if arg.children.first.respond_to?(:kwsplat_type?) && arg.children.first&.kwsplat_type?
+
+ # parser thinks `a: :b, c: :d` is hash type, it's actually kwargs
+ return if arg.hash_type? && !arg.source.match(/\A{/)
+
+ add_offense(arg)
+ end
+
+ def autocorrect(arg)
+ lambda do |corrector|
+ if arg.hash_type?
+ kwarg = arg.source.sub(/\A{\s*/, '').sub(/\s*}\z/, '')
+ corrector.replace(arg, kwarg)
+ elsif arg.splat_type?
+ corrector.insert_before(arg, '*')
+ else
+ corrector.insert_before(arg, '**')
+ end
+ end
+ end
+
+ private
+
+ def known_match?(file_path, line_number, method_name)
+ file_path_from_root = file_path.sub(File.expand_path('../../..', __dir__), '')
+
+ method_name = 'initialize' if method_name == 'new'
+
+ self.class.keyword_warnings.any? do |warning|
+ warning.include?("#{file_path_from_root}:#{line_number}") && warning.include?("called method `#{method_name}'")
+ end
+ end
+
+ def self.keyword_warnings
+ @keyword_warnings ||= keywords_list
+ end
+
+ def self.keywords_list
+ hash = Dir.glob(DEPRECATIONS_GLOB).each_with_object({}) do |file, hash|
+ hash.merge!(YAML.safe_load(File.read(file)))
+ end
+
+ hash.values.flatten.select { |str| str.include?(KEYWORD_DEPRECATION_STR) }.uniq
+ end
+ end
+ end
+ end
+end