summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2017-12-25 18:20:50 +0800
committerLin Jen-Shin <godfat@godfat.org>2017-12-26 17:18:10 +0800
commit8139895b4362817cf947431fab9c95ce223b87ae (patch)
tree3419ad5cdde44bad709024a886c523f57e7b4881 /lib
parent29749f92b7f86d45af41509262601e47ee848d92 (diff)
downloadgitlab-ce-8139895b4362817cf947431fab9c95ce223b87ae.tar.gz
Use `Gitlab::Utils::Override` over defined?(super)
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/utils/override.rb111
-rw-r--r--lib/tasks/dev.rake5
-rw-r--r--lib/tasks/lint.rake12
3 files changed, 128 insertions, 0 deletions
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
new file mode 100644
index 00000000000..8bf6bcb1fe2
--- /dev/null
+++ b/lib/gitlab/utils/override.rb
@@ -0,0 +1,111 @@
+module Gitlab
+ module Utils
+ module Override
+ class Extension
+ def self.verify_class!(klass, method_name)
+ instance_method_defined?(klass, method_name) ||
+ raise(
+ NotImplementedError.new(
+ "#{klass}\##{method_name} doesn't exist!"))
+ end
+
+ def self.instance_method_defined?(klass, name, include_super: true)
+ klass.instance_methods(include_super).include?(name) ||
+ klass.private_instance_methods(include_super).include?(name)
+ end
+
+ attr_reader :subject
+
+ def initialize(subject)
+ @subject = subject
+ end
+
+ def add_method_name(method_name)
+ method_names << method_name
+ end
+
+ def add_class(klass)
+ classes << klass
+ end
+
+ def verify!
+ classes.each do |klass|
+ index = klass.ancestors.index(subject)
+ parents = klass.ancestors.drop(index + 1)
+
+ method_names.each do |method_name|
+ parents.any? do |parent|
+ self.class.instance_method_defined?(
+ parent, method_name, include_super: false)
+ end ||
+ raise(
+ NotImplementedError.new(
+ "#{klass}\##{method_name} doesn't exist!"))
+ end
+ end
+ end
+
+ private
+
+ def method_names
+ @method_names ||= []
+ end
+
+ def classes
+ @classes ||= []
+ end
+ end
+
+ # Instead of writing patterns like this:
+ #
+ # def f
+ # raise NotImplementedError unless defined?(super)
+ #
+ # true
+ # end
+ #
+ # We could write it like:
+ #
+ # extend ::Gitlab::Utils::Override
+ #
+ # override :f
+ # def f
+ # true
+ # end
+ #
+ # This would make sure we're overriding something. See:
+ # https://gitlab.com/gitlab-org/gitlab-ee/issues/1819
+ def override(method_name)
+ return unless ENV['STATIC_VERIFICATION']
+
+ if is_a?(Class)
+ Extension.verify_class!(self, method_name)
+ else # We delay the check for modules
+ Override.extensions[self] ||= Extension.new(self)
+ Override.extensions[self].add_method_name(method_name)
+ end
+ end
+
+ def included(base = nil)
+ return super if base.nil? # Rails concern, ignoring it
+
+ super
+
+ if base.is_a?(Class) # We could check for Class in `override`
+ # This could be `nil` if `override` was never called
+ Override.extensions[self]&.add_class(base)
+ end
+ end
+
+ alias_method :prepended, :included
+
+ def self.extensions
+ @extensions ||= {}
+ end
+
+ def self.verify!
+ extensions.values.each(&:verify!)
+ end
+ end
+ end
+end
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index e65609d7001..4beb94eeb8e 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -7,4 +7,9 @@ namespace :dev do
Rake::Task["gitlab:setup"].invoke
Rake::Task["gitlab:shell:setup"].invoke
end
+
+ desc "GitLab | Eager load application"
+ task load: :environment do
+ Rails.application.eager_load!
+ end
end
diff --git a/lib/tasks/lint.rake b/lib/tasks/lint.rake
index 7b63e93db0e..3ab406eff2c 100644
--- a/lib/tasks/lint.rake
+++ b/lib/tasks/lint.rake
@@ -1,5 +1,17 @@
unless Rails.env.production?
namespace :lint do
+ task :static_verification_env do
+ ENV['STATIC_VERIFICATION'] = 'true'
+ end
+
+ desc "GitLab | lint | Static verification"
+ task static_verification: %w[
+ lint:static_verification_env
+ dev:load
+ ] do
+ Gitlab::Utils::Override.verify!
+ end
+
desc "GitLab | lint | Lint JavaScript files using ESLint"
task :javascript do
Rake::Task['eslint'].invoke