module NeuronCheckSystem::Kernel
メソッド追加時のフック処理や、属性宣言メソッドのオーバーライドなどを定義したメインモジュール NeuronCheckを行いたい対象のモジュールやクラスにextendすることで使用する
Public Instance Methods
__neuron_check_attr_defined(used_method_name, names, use_reader: false, use_writer: false)
click to toggle source
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 65 def __neuron_check_attr_defined(used_method_name, names, use_reader: false, use_writer: false) # 直前にNeuronCheck宣言部があれば、その宣言内容を各メソッドへ登録する if (declaration = @__neuron_check_last_declaration) then # 短縮記法による宣言かどうかで分岐 if declaration.shorthand then # 短縮記法の場合は、引数が2つ以上宣言されている、もしくは戻り値が宣言されている場合にエラーとする if declaration.arg_matchers.size >= 2 or declaration.return_matcher then raise NeuronCheckSystem::DeclarationError, "expected value must be one for `#{used_method_name}'", declaration.declared_caller_locations end # 引数1用のマッチャを属性用のマッチャとみなす target_attr_matcher = declaration.arg_matchers[0] else # 通常の宣言の場合、引数、戻り値の宣言がされている場合はエラーとする if declaration.arg_matchers.size >= 1 or declaration.return_matcher then raise NeuronCheckSystem::DeclarationError, "`args' or `returns' declaration can be used only for method definition, but used for `#{used_method_name}'", declaration.declared_caller_locations end target_attr_matcher = declaration.attr_matcher end # 属性チェック用モジュールに対する処理 @__neuron_check_attr_check_module.module_eval do # 属性1つごとに処理 names.each do |attr_name| # 属性チェック用モジュールに、readerチェック用のラッパーメソッドを追加する if use_reader then define_method(attr_name) do # 通常の処理を呼び出す val = super() # 属性宣言があればチェック処理 if target_attr_matcher then unless target_attr_matcher.match?(val, self) then context_caption = "value of attribute `#{self.class.name}##{attr_name}'" raise NeuronCheckError, target_attr_matcher.get_error_message(declaration, context_caption, val), (NeuronCheck.debug? ? caller : caller(1)) end end end end # 属性チェック用モジュールに、writerチェック用のラッパーメソッドを追加する if use_writer then define_method("#{attr_name}=") do |val| # 属性宣言があればチェック処理 if target_attr_matcher then unless target_attr_matcher.match?(val, self) then context_caption = "value of attribute `#{self.class.name}##{attr_name}'" raise NeuronCheckError, target_attr_matcher.get_error_message(declaration, context_caption, val, phrase_after_but: 'set'), (NeuronCheck.debug? ? caller : caller(1)) end end # 通常の処理を呼び出す super(val) end end end end # 属性1つごとに処理 names.each do |attr_name| # 登録実行 NeuronCheckSystem::ATTR_DECLARATIONS[self][attr_name] = declaration declaration.assigned_class_or_module = self declaration.assigned_attribute_name = attr_name end # チェック処理の追加が完了したら、「最後に宣言した内容」を表すクラスインスタンス変数をnilに戻す @__neuron_check_last_declaration = nil end end
__neuron_check_method_added_hook(target_cls_or_mod, method_name, met, singleton_original_class = nil)
click to toggle source
メソッド/特異メソッドを定義したときの共通処理
# File lib/neuroncheck/kernel.rb, line 159 def __neuron_check_method_added_hook(target_cls_or_mod, method_name, met, singleton_original_class = nil) singleton = !(singleton_original_class.nil?) # メソッド定義時のフックが無効化されている場合は何もしない return unless @__neuron_check_method_added_hook_enabled # 直前にNeuronCheck宣言部があれば、その宣言内容を登録する if (declaration = @__neuron_check_last_declaration) then # あらかじめ登録と、メソッドやクラスとの紐付けを行っておく # この処理を先に行わないと正しく名前を取得できない NeuronCheckSystem::METHOD_DECLARATIONS[target_cls_or_mod][method_name] = declaration declaration.assigned_class_or_module = target_cls_or_mod declaration.assigned_method = met declaration.assigned_singleton_original_class = singleton_original_class # 宣言に引数チェックが含まれている場合、宣言部の引数の数が、実際のメソッドの引数の数を超えていないかをチェック # 超えていれば宣言エラーとする if declaration.arg_matchers.size > met.parameters.size then raise NeuronCheckSystem::DeclarationError, "given arguments number of ##{method_name} greater than method definition - expected #{met.parameters.size} args, but #{declaration.arg_matchers.size} args were declared" end # パラメータの中にブロック型の引数が含まれているが # そのパラメータが、anyでもblockでもない型である場合はエラー met.parameters.each_with_index do |param_info, def_param_index| param_type, param_name = param_info if param_type == :block and (matcher = declaration.arg_matchers[def_param_index]) then next if matcher.respond_to?(:keyword_name) and matcher.keyword_name == 'any' next if matcher.respond_to?(:keyword_name) and matcher.keyword_name == 'block' context_caption = "#{NeuronCheckSystem::Utils.ordinalize(def_param_index + 1)} argument `#{param_name}' of `#{declaration.signature_caption_name_only}'" raise NeuronCheckSystem::DeclarationError, "#{context_caption} is block argument - it can be specified only keyword `any' or `block'" end end # 特異メソッドでなく、メソッド名が「initialize」であるにもかかわらず、returns宣言が含まれている場合はエラー if not singleton and method_name == :initialize and declaration.return_matcher then raise NeuronCheckSystem::DeclarationError, "returns declaration cannot be used with `#initialize' method" end # チェック処理の追加が完了したら、「最後に宣言した内容」を表すクラスインスタンス変数をnilに戻す @__neuron_check_last_declaration = nil end end
attr(name, assignable = false)
click to toggle source
属性定義
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 13 def attr(name, assignable = false) @__neuron_check_method_added_hook_enabled = false begin # 元処理を呼ぶ super # NeuronCheck用の属性定義時処理を呼ぶ __neuron_check_attr_defined(__method__, [name], use_reader: true, use_writer: assignable) ensure @__neuron_check_method_added_hook_enabled = true end end
attr_accessor(*names)
click to toggle source
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 52 def attr_accessor(*names) @__neuron_check_method_added_hook_enabled = false begin # 元処理を呼ぶ super # NeuronCheck用の属性定義時処理を呼ぶ __neuron_check_attr_defined(__method__, names, use_reader: true, use_writer: true) ensure @__neuron_check_method_added_hook_enabled = true end end
attr_reader(*names)
click to toggle source
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 26 def attr_reader(*names) @__neuron_check_method_added_hook_enabled = false begin # 元処理を呼ぶ super # NeuronCheck用の属性定義時処理を呼ぶ __neuron_check_attr_defined(__method__, names, use_reader: true, use_writer: false) ensure @__neuron_check_method_added_hook_enabled = true end end
attr_writer(*names)
click to toggle source
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 39 def attr_writer(*names) @__neuron_check_method_added_hook_enabled = false begin # 元処理を呼ぶ super # NeuronCheck用の属性定義時処理を呼ぶ __neuron_check_attr_defined(__method__, names, use_reader: false, use_writer: true) ensure @__neuron_check_method_added_hook_enabled = true end end
method_added(name)
click to toggle source
インスタンスメソッド定義を追加したときの処理
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 141 def method_added(name) # まずは親処理を呼ぶ super # メイン処理をコール __neuron_check_method_added_hook(self, name, self.instance_method(name)) end
singleton_method_added(name)
click to toggle source
特異メソッド定義を追加したときの処理
Calls superclass method
# File lib/neuroncheck/kernel.rb, line 150 def singleton_method_added(name) # まずは親処理を呼ぶ super # メイン処理をコール __neuron_check_method_added_hook(self.singleton_class, name, self.singleton_class.instance_method(name), self) end