Class: Necropsy::Analyzers::Static::RTA

Inherits:
Necropsy::Analyzer show all
Defined in:
lib/necropsy/analyzers/static/rta.rb

Constant Summary collapse

ENUMERABLE_MESSAGES =
%w[
  all? any? chunk collect count cycle detect drop drop_while each_cons each_entry
  each_slice each_with_index each_with_object entries filter find find_all flat_map
  grep group_by include? inject map max min none? one? partition reduce reject
  reverse_each select sort sort_by take take_while to_a to_h
].freeze
COMPARISON_MESSAGES =
%w[< <= > >= between? clamp sort sort_by max min].freeze

Instance Method Summary collapse

Instance Method Details

#analyze(graph, _project) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/necropsy/analyzers/static/rta.rb', line 15

def analyze(graph, _project)
  edge_evidences = expanded_call_sites(graph).flat_map do |site|
    graph.resolve_call_site(site, rta: true).map do |candidate|
      EdgeEvidence.new(
        caller_id: site.caller_id,
        callee_id: candidate.id,
        evidence: evidence(
          kind: :call_edge,
          details: "RTA candidate at #{site.file}:#{site.line}",
          metadata: site.to_h.merge('instantiated_classes' => graph.instantiated_classes.to_a.sort)
        )
      )
    end
  end

  AnalyzerResult.new(
    edge_evidences: edge_evidences,
    alive_evidences: [],
    uncertainties: {},
    observation: {}
  )
end

#expanded_call_sites(graph) ⇒ Object



47
48
49
50
51
# File 'lib/necropsy/analyzers/static/rta.rb', line 47

def expanded_call_sites(graph)
  graph.call_sites.flat_map do |site|
    [site, *implicit_sites(site)]
  end
end

#implicit_messages(message) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/necropsy/analyzers/static/rta.rb', line 69

def implicit_messages(message)
  messages = []
  messages << 'each' if ENUMERABLE_MESSAGES.include?(message) && message != 'each'
  messages << '<=>' if COMPARISON_MESSAGES.include?(message)
  messages << 'to_s' if %w[puts print warn].include?(message)
  messages
end

#implicit_sites(site) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/necropsy/analyzers/static/rta.rb', line 53

def implicit_sites(site)
  implicit_messages(site.message).map do |message|
    CallSite.new(
      caller_id: site.caller_id,
      message: message,
      receiver_kind: site.receiver_kind,
      receiver_name: site.receiver_name,
      file: site.file,
      line: site.line,
      test: site.test,
      dynamic: site.dynamic,
      metadata: site..merge('implicit_from' => site.message)
    )
  end
end

#profileObject



38
39
40
41
42
43
44
45
# File 'lib/necropsy/analyzers/static/rta.rb', line 38

def profile
  AnalyzerProfile.new(
    name: :rta,
    kind: :static,
    soundness: :partial,
    description: 'Narrows instance dispatch to classes that are constructed in the scanned program.'
  )
end