여기에는 '사용 된'의미와 관련하여 다소 모호한 부분이 있습니다. b.rb (역시 사용되는)가 D.new
을 결국 호출하기 때문에 분명히 d가 사용됩니다. 우리가 '사용'을 의미하는주의 경우 "코드 중이 아닌, 해당 파일에서 실행 된 과정을 필요로"1.9.3
require 'set'
def analyze(filename)
require_depth = 0
files = Set.new
set_trace_func(lambda do |event, file, line, id, binding, classname|
case event
when 'call'then require_depth += 1 if id == :require && classname == Kernel
when 'return' then require_depth -= 1 if id == :require && classname == Kernel
when 'line'
files << file if require_depth == 0
end
end)
load filename
set_trace_func nil
files.reject {|f| f == __FILE__ || f =~ %r{/lib/ruby/site_ruby}}
end
당신이 사용하는 거라고 내가 루비에 얻을 수있는 다음 코드는 가까이 analyse 'a.rb'
(관련된 모든 파일이로드 경로에 있다고 가정)을 실행하십시오. 이것이하는 일은 루비의 set_trace_func를 사용하여 현재 일어나고있는 일을 경청합니다. 첫 번째 부분은 요구하는 동안 발생하는 모든 것을 무시하려는 조잡한 시도입니다. 그런 다음 실행 된 루비의 모든 행의 파일 이름을 누적합니다. 마지막 줄은 정크를 제거하는 것입니다 (예 : 패치가 필요로하는 rubygems 파일).
B.new가 실행될 때 b.rb의 코드 행이 실제로 실행되지 않습니다. 테스트 예제에서는 실제로 작동하지 않습니다. 그러나 B (와 C, D 등)가 초기화 메소드 (또는 호출되는 코드 라인)를 가지고 있다면 원하는 결과를 얻어야합니다. 그것은 꽤 단순한 물건이고 모든 재료에 의해 바보가 될 수 있습니다. 특히 B에서 메서드를 호출했지만 해당 메서드의 구현이 b.rb (예 : attr_accessor로 정의 된 접근 자)가 아니면 b.rb가 기록되지 않습니다.
더 나은 호출 이벤트를 사용하지만 훨씬 더 set_trace_func 함께 할 수 있다고 생각하지 않습니다.
ruby 2.0을 사용하는 경우 set_trace_func
을 대신하는 TracePoint를 사용할 수 있습니다. 우리는 방법은 테스트 예를 들어 A, B, C를 반환하지 그래서
require 'set'
def analyze(filename)
require_depth = 0
files = Set.new
classes_to_files = {}
trace = TracePoint.new(:call, :line, :return, :c_call, :class) do |tp|
case tp.event
when :class
classes_to_files[tp.self] = tp.path
when :call, :c_call then
if tp.method_id == :require && tp.defined_class == Kernel
require_depth += 1
else
if require_depth == 0
if path = classes_to_files[tp.self] || classes_to_files[tp.self.class]
files << path
end
end
end
when :return then require_depth -= 1 if tp.method_id == :require && tp.defined_class == Kernel
when :line
if require_depth == 0
files << tp.path
end
end
end
trace.enable
load filename
trace.disable
files.reject {|f| f == __FILE__ || f =~ %r{/lib/ruby/site_ruby}}
end
에 호출 된 클래스를 얻기 위해 그것의 쉽게 전화를 추적 할 때 특히 약간 다른 의미를 가지고 있습니다. 실제로 실행되는 코드에 대해서만 알고 있다는 근본적인 제한이 있습니다.
'e.rb'를 제외하고'c.rb'를 포함하는 것은 해결해야 할 어려운 문제입니다 ("정지 문제"와 동등 할 수도 있습니다, 확실하지 않습니다). 루비 코드를 완전히 파싱하고 가능한 모든 코드 경로를 이해해야합니다. 단순한 경량 의존성 (예 : 클래스 정의 및 기본 인스턴스 생성) 만 찾으면이 90 %를 정확하게 만들 수 있습니다. 따라서 90 %의 정확도가 수용 가능합니까? –
@NeilSlater 여기에 가입 할 수 있습니까? - http://chat.stackoverflow.com/rooms/27184/ruby-conceptual? –
@NeilSlater 예 90 % 또는 그 이하도 OK입니다. – alexloh