これはデバッグ目的のためだけだと思います。たとえば、テストのためにスリープステートメントを入れていて、コミット時にそれらを入れたくない場合などです。その場合、以下のコードはあなたが望むことをします:
require 'ripper'
class MethodParser
def initialize(source)
@ast = Ripper.sexp(source)
end
def is_method_called?(method_name)
search_ast_for_method(@ast, method_name)
end
private
def is_top_level_method_call(ast, method_name)
# firstly check if possible command block
unless ast.is_a?(Array) && ast.length > 1 && ast[1].is_a?(Array)
return false
end
# now check if it is a function call or command, and check the method name
if [:command, :fcall].include? ast[0]
ast[1].include?(method_name.to_s)
else
false
end
end
def search_ast_for_method(ast, method_name)
return true if is_top_level_method_call(ast, method_name)
return false unless ast.is_a? Array
ast.any? { |e| search_ast_for_method(e, method_name) }
end
end
使用例:
>> m = MethodParser.new <<EOF
class TestClass
def method
puts "hello"
sleep(42)
end
end
EOF
=> #<MethodParser:0x007f9df3a493c0 @ast=[:program, [[:class, [:const_ref, [:@const, "TestClass", [1, 6]]], nil, [:bodystmt, [[:def, [:@ident, "method", [2, 6]], [:params, nil, nil, nil, nil, nil, nil, nil], [:bodystmt, [[:command, [:@ident, "puts", [3, 4]], [:args_add_block, [[:string_literal, [:string_content, [:@tstring_content, "hello", [3, 10]]]]], false]], [:method_add_arg, [:fcall, [:@ident, "sleep", [4, 4]]], [:arg_paren, [:args_add_block, [[:@int, "42", [4, 10]]], false]]]], nil, nil, nil]]], nil, nil, nil]]]]>
>> m.is_method_called? :sleep
=> true
>> m.is_method_called? :puts
=> true
>> m.is_method_called? :hello
=> false
>> m.is_method_called? "hello"
=> false
動的なメソッドの呼び出し、または単にメソッドのエイリアシングはこれをバイパスすることに注意してeval("sl" + "eep 4")
くださいsend(:sleep, 4)
。コミットされたコードの健全性テストだけであれば、それで十分です。
最後にKernel.sleep 4
、必要に応じて修正するのは難しくありませんが、でスリープを検出しません。