Class: Brakeman::CallIndex

Inherits:
Object show all
Defined in:
lib/brakeman/call_index.rb

Overview

Stores call sites to look up later.

Instance Method Summary collapse

Constructor Details

#initialize(calls) ⇒ CallIndex

Initialize index with calls from FindAllCalls



7
8
9
10
11
12
13
14
# File 'lib/brakeman/call_index.rb', line 7

def initialize calls
  @calls_by_method = Hash.new { |h,k| h[k] = [] }
  @calls_by_target = Hash.new { |h,k| h[k] = [] }
  @methods = Set.new
  @targets = Set.new

  index_calls calls
end

Instance Method Details

#find_calls(options) ⇒ Object

Find calls matching specified option hash.

Options:

* :target - symbol, array of symbols, or regular expression to match target(s)
* :method - symbol, array of symbols, or regular expression to match method(s)
* :chained - boolean, whether or not to match against a whole method chain (false by default)
* :nested - boolean, whether or not to match against a method call that is a target itself (false by default)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/brakeman/call_index.rb', line 24

def find_calls options
  target = options[:target] || options[:targets]
  method = options[:method] || options[:methods]
  nested = options[:nested]
  
  if options[:chained]
    return find_chain options
  #Find by narrowest category
  elsif target and method and target.is_a? Array and method.is_a? Array
    if target.length > method.length
      calls = filter_by_target calls_by_methods(method), target
    else
      calls = calls_by_targets(target)
      calls = filter_by_method calls, method
    end

  #Find by target, then by methods, if provided
  elsif target
    calls = calls_by_target target

    if calls and method
      calls = filter_by_method calls, method
    end

  #Find calls with no explicit target
  #with either :target => nil or :target => false
  elsif options.key? :target and not target and method
    calls = calls_by_method method
    calls = filter_by_target calls, nil

  #Find calls by method
  elsif method
    calls = calls_by_method method
  else
    notify "Invalid arguments to CallCache#find_calls: #{options.inspect}"
  end

  return [] if calls.nil?

  #Remove calls that are actually targets of other calls
  #Unless those are explicitly desired
  calls = filter_nested calls unless nested

  calls
end

#index_calls(calls) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/brakeman/call_index.rb', line 106

def index_calls calls
  calls.each do |call|
    @methods << call[:method].to_s
    @targets << call[:target].to_s if call[:target].is_a? Symbol
    @calls_by_method[call[:method]] << call
    @calls_by_target[call[:target]] << call
  end
end

#remove_indexes_by_class(classes) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/brakeman/call_index.rb', line 88

def remove_indexes_by_class classes
  @calls_by_method.each do |name, calls|
    calls.delete_if do |call|
      call[:location][0] == :class and classes.include? call[:location][1]
    end

    @methods.delete name.to_s if calls.empty?
  end

  @calls_by_target.each do |name, calls|
    calls.delete_if do |call|
      call[:location][0] == :class and classes.include? call[:location][1]
    end

    @targets.delete name.to_s if calls.empty?
  end
end

#remove_template_indexes(template_name = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/brakeman/call_index.rb', line 70

def remove_template_indexes template_name = nil
  @calls_by_method.each do |name, calls|
    calls.delete_if do |call|
      from_template call, template_name
    end

    @methods.delete name.to_s if calls.empty?
  end

  @calls_by_target.each do |name, calls|
    calls.delete_if do |call|
      from_template call, template_name
    end

    @targets.delete name.to_s if calls.empty?
  end
end