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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-28 12:10:32 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-28 12:10:32 +0300
commitc4b69460e8dd4921eb20fa78b47ceff294d725dc (patch)
tree9be3f5c3913ead9eeb5f183ac7a163b193412967 /rubocop
parent540c69c58c9e60f2d9b47987afe5e020593d39ac (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'rubocop')
-rw-r--r--rubocop/cop/migration/refer_to_index_by_name.rb67
1 files changed, 67 insertions, 0 deletions
diff --git a/rubocop/cop/migration/refer_to_index_by_name.rb b/rubocop/cop/migration/refer_to_index_by_name.rb
new file mode 100644
index 00000000000..fbf3c0d7030
--- /dev/null
+++ b/rubocop/cop/migration/refer_to_index_by_name.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class ReferToIndexByName < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'migration methods that refer to existing indexes must do so by name'
+
+ def_node_matcher :match_index_exists, <<~PATTERN
+ (send _ :index_exists? _ _ (hash $...) ?)
+ PATTERN
+
+ def_node_matcher :match_remove_index, <<~PATTERN
+ (send _ :remove_index _ $_)
+ PATTERN
+
+ def_node_matcher :match_remove_concurrent_index, <<~PATTERN
+ (send _ :remove_concurrent_index _ _ (hash $...) ?)
+ PATTERN
+
+ def_node_matcher :name_option?, <<~PATTERN
+ (pair {(sym :name) (str "name")} _)
+ PATTERN
+
+ def on_def(node)
+ return unless in_migration?(node)
+
+ node.each_descendant(:send) do |send_node|
+ next unless index_exists_offense?(send_node) || removing_index_offense?(send_node)
+
+ add_offense(send_node, location: :selector)
+ end
+ end
+
+ private
+
+ def index_exists_offense?(send_node)
+ match_index_exists(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def removing_index_offense?(send_node)
+ remove_index_offense?(send_node) || remove_concurrent_index_offense?(send_node)
+ end
+
+ def remove_index_offense?(send_node)
+ match_remove_index(send_node) do |column_or_options_node|
+ break true unless column_or_options_node.type == :hash
+
+ column_or_options_node.children.none? { |pair| name_option?(pair) }
+ end
+ end
+
+ def remove_concurrent_index_offense?(send_node)
+ match_remove_concurrent_index(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def needs_name_option?(option_nodes)
+ option_nodes.empty? || option_nodes.first.none? { |node| name_option?(node) }
+ end
+ end
+ end
+ end
+end