diff options
Diffstat (limited to 'rubocop/cop')
-rw-r--r-- | rubocop/cop/active_record_dependent.rb | 26 | ||||
-rw-r--r-- | rubocop/cop/active_record_serialize.rb (renamed from rubocop/cop/activerecord_serialize.rb) | 2 | ||||
-rw-r--r-- | rubocop/cop/in_batches.rb | 16 | ||||
-rw-r--r-- | rubocop/cop/migration/add_column_with_default_to_large_table.rb | 3 | ||||
-rw-r--r-- | rubocop/cop/migration/hash_index.rb | 51 | ||||
-rw-r--r-- | rubocop/cop/project_path_helper.rb | 51 |
6 files changed, 148 insertions, 1 deletions
diff --git a/rubocop/cop/active_record_dependent.rb b/rubocop/cop/active_record_dependent.rb new file mode 100644 index 00000000000..8d15f150885 --- /dev/null +++ b/rubocop/cop/active_record_dependent.rb @@ -0,0 +1,26 @@ +require_relative '../model_helpers' + +module RuboCop + module Cop + # Cop that prevents the use of `dependent: ...` in ActiveRecord models. + class ActiveRecordDependent < RuboCop::Cop::Cop + include ModelHelpers + + MSG = 'Do not use `dependent: to remove associated data, ' \ + 'use foreign keys with cascading deletes instead'.freeze + + METHOD_NAMES = [:has_many, :has_one, :belongs_to].freeze + + def on_send(node) + return unless in_model?(node) + return unless METHOD_NAMES.include?(node.children[1]) + + node.children.last.each_node(:pair) do |pair| + key_name = pair.children[0].children[0] + + add_offense(pair, :expression) if key_name == :dependent + end + end + end + end +end diff --git a/rubocop/cop/activerecord_serialize.rb b/rubocop/cop/active_record_serialize.rb index 9bdcc3b4c34..204caf37f8b 100644 --- a/rubocop/cop/activerecord_serialize.rb +++ b/rubocop/cop/active_record_serialize.rb @@ -3,7 +3,7 @@ require_relative '../model_helpers' module RuboCop module Cop # Cop that prevents the use of `serialize` in ActiveRecord models. - class ActiverecordSerialize < RuboCop::Cop::Cop + class ActiveRecordSerialize < RuboCop::Cop::Cop include ModelHelpers MSG = 'Do not store serialized data in the database, use separate columns and/or tables instead'.freeze diff --git a/rubocop/cop/in_batches.rb b/rubocop/cop/in_batches.rb new file mode 100644 index 00000000000..c0240187e66 --- /dev/null +++ b/rubocop/cop/in_batches.rb @@ -0,0 +1,16 @@ +require_relative '../model_helpers' + +module RuboCop + module Cop + # Cop that prevents the use of `in_batches` + class InBatches < RuboCop::Cop::Cop + MSG = 'Do not use `in_batches`, use `each_batch` from the EachBatch module instead'.freeze + + def on_send(node) + return unless node.children[1] == :in_batches + + add_offense(node, :selector) + end + end + end +end diff --git a/rubocop/cop/migration/add_column_with_default_to_large_table.rb b/rubocop/cop/migration/add_column_with_default_to_large_table.rb index 2372e6b60ea..87788b0d9c2 100644 --- a/rubocop/cop/migration/add_column_with_default_to_large_table.rb +++ b/rubocop/cop/migration/add_column_with_default_to_large_table.rb @@ -20,8 +20,11 @@ module RuboCop 'necessary'.freeze LARGE_TABLES = %i[ + ci_builds events issues + merge_request_diff_files + merge_request_diffs merge_requests namespaces notes diff --git a/rubocop/cop/migration/hash_index.rb b/rubocop/cop/migration/hash_index.rb new file mode 100644 index 00000000000..2cc59691d84 --- /dev/null +++ b/rubocop/cop/migration/hash_index.rb @@ -0,0 +1,51 @@ +require 'set' +require_relative '../../migration_helpers' + +module RuboCop + module Cop + module Migration + # Cop that prevents the use of hash indexes in database migrations + class HashIndex < RuboCop::Cop::Cop + include MigrationHelpers + + MSG = 'hash indexes should be avoided at all costs since they are not ' \ + 'recorded in the PostgreSQL WAL, you should use a btree index instead'.freeze + + NAMES = Set.new([:add_index, :index, :add_concurrent_index]).freeze + + def on_send(node) + return unless in_migration?(node) + + name = node.children[1] + + return unless NAMES.include?(name) + + opts = node.children.last + + return unless opts && opts.type == :hash + + opts.each_node(:pair) do |pair| + next unless hash_key_type(pair) == :sym && + hash_key_name(pair) == :using + + if hash_key_value(pair).to_s == 'hash' + add_offense(pair, :expression) + end + end + end + + def hash_key_type(pair) + pair.children[0].type + end + + def hash_key_name(pair) + pair.children[0].children[0] + end + + def hash_key_value(pair) + pair.children[1].children[0] + end + end + end + end +end diff --git a/rubocop/cop/project_path_helper.rb b/rubocop/cop/project_path_helper.rb new file mode 100644 index 00000000000..3e1ce71ac06 --- /dev/null +++ b/rubocop/cop/project_path_helper.rb @@ -0,0 +1,51 @@ +module RuboCop + module Cop + class ProjectPathHelper < RuboCop::Cop::Cop + MSG = 'Use short project path helpers without explicitly passing the namespace: ' \ + '`foo_project_bar_path(project, bar)` instead of ' \ + '`foo_namespace_project_bar_path(project.namespace, project, bar)`.'.freeze + + METHOD_NAME_PATTERN = /\A([a-z_]+_)?namespace_project(?:_[a-z_]+)?_(?:url|path)\z/.freeze + + def on_send(node) + return unless method_name(node).to_s =~ METHOD_NAME_PATTERN + + namespace_expr, project_expr = arguments(node) + return unless namespace_expr && project_expr + + return unless namespace_expr.type == :send + return unless method_name(namespace_expr) == :namespace + return unless receiver(namespace_expr) == project_expr + + add_offense(node, :selector) + end + + def autocorrect(node) + helper_name = method_name(node).to_s.sub('namespace_project', 'project') + + arguments = arguments(node) + arguments.shift # Remove namespace argument + + replacement = "#{helper_name}(#{arguments.map(&:source).join(', ')})" + + lambda do |corrector| + corrector.replace(node.source_range, replacement) + end + end + + private + + def receiver(node) + node.children[0] + end + + def method_name(node) + node.children[1] + end + + def arguments(node) + node.children[2..-1] + end + end + end +end |