Class: Laser::Analysis::DispatchResults
- Inherits:
-
Object
- Object
- Laser::Analysis::DispatchResults
show all
- Defined in:
- lib/laser/analysis/bootstrap/dispatch_results.rb
Overview
Collects the results of attempted dispatches and calculates the return
type, raise type, and raise frequency.
Is used whenever a dispatch is discovered that needs analysis. This
includes, for example, performing CPA and analyzing a call to
send/public_send.
Is responsible for noting that a method has been used, as this is the
central place for the logic pertaining to success/failure on dispatch. Keep
in mind: a method isn't used if it is called with incorrect arity, and
that arity checking should occur here.
Defined Under Namespace
Classes: ArityError, PrivacyError
Instance Attribute Summary (collapse)
Instance Method Summary
(collapse)
-
- (Object) add_samples_from_dispatch(methods, self_type, cartesian, ignore_privacy)
-
- (Object) arity_failure_frequency
Arity-related dispatch issues ############.
-
- (Object) check_arity(method, self_type, proposed_arity)
-
- (Object) check_privacy(method, self_type, ignore_privacy)
-
- (Object) fails_arity(receiver_class, method_name, provided, expected)
-
- (Object) fails_dispatch(raise_type)
-
- (Object) fails_privacy(receiver_class, method_name)
-
- (DispatchResults) initialize
constructor
A new instance of DispatchResults.
-
- (Object) normal_dispatch(method, self_type, cartesian)
-
- (Object) normal_failure_frequency
Calculated dispatch issues ###########.
-
- (Object) passes_arity
-
- (Object) passes_dispatch(return_type)
-
- (Object) passes_privacy
-
- (Object) privacy_failure_frequency
Privacy-related dispatch issues ############.
-
- (Object) raise_frequency
-
- (Object) raise_type
Result Accessors ##############.
Constructor Details
A new instance of DispatchResults
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 32
def initialize
@raise_type = Types::EMPTY
@result_type = Types::EMPTY
@privacy_failures = 0
@privacy_samples = 0
@privacy_errors = Set[]
@arity_failures = 0
@arity_samples = 0
@arity_errors = Set[]
@normal_failures = 0
@normal_samples = 0
end
|
Instance Attribute Details
- (Object) result_type
Returns the value of attribute result_type
30
31
32
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 30
def result_type
@result_type
end
|
Instance Method Details
- (Object) add_samples_from_dispatch(methods, self_type, cartesian, ignore_privacy)
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 45
def add_samples_from_dispatch(methods, self_type, cartesian, ignore_privacy)
if methods.empty?
@privacy_failures += 1
@privacy_samples += 1
@raise_type |= ClassRegistry['NoMethodError'].as_type
end
methods.each do |method|
next unless check_privacy(method, self_type, ignore_privacy)
cartesian.each do |*type_list, block_type|
next unless check_arity(method, self_type, type_list.size)
method.been_used!
normal_dispatch(method, self_type, cartesian)
end
end
end
|
- (Object) arity_failure_frequency
Arity-related dispatch issues ############
124
125
126
127
128
129
130
131
132
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 124
def arity_failure_frequency
if @arity_failures == 0
Frequency::NEVER
elsif @arity_failures == @arity_samples
Frequency::ALWAYS
else
Frequency::MAYBE
end
end
|
- (Object) check_arity(method, self_type, proposed_arity)
79
80
81
82
83
84
85
86
87
88
89
90
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 79
def check_arity(method, self_type, proposed_arity)
result = false
self_type.possible_classes.each do |self_class|
if method.valid_arity?(proposed_arity)
passes_arity
result = true
else
fails_arity(self_class, method.name, proposed_arity, method.arity)
end
end
result
end
|
- (Object) check_privacy(method, self_type, ignore_privacy)
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 61
def check_privacy(method, self_type, ignore_privacy)
result = false
if ignore_privacy
passes_privacy
result = true
else
self_type.possible_classes.each do |self_class|
if self_class.visibility_for(method.name) == :public
passes_privacy
result = true
else
fails_privacy(self_class, method.name)
end
end
end
result
end
|
- (Object) fails_arity(receiver_class, method_name, provided, expected)
138
139
140
141
142
143
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 138
def fails_arity(receiver_class, method_name, provided, expected)
@arity_errors << ArityError.new(receiver_class, method_name, provided, expected)
@arity_samples += 1
@arity_failures += 1
@raise_type |= ClassRegistry['ArgumentError'].as_type
end
|
- (Object) fails_dispatch(raise_type)
185
186
187
188
189
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 185
def fails_dispatch(raise_type)
@raise_type |= raise_type
@normal_failures += 1
@normal_samples += 1
end
|
- (Object) fails_privacy(receiver_class, method_name)
161
162
163
164
165
166
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 161
def fails_privacy(receiver_class, method_name)
@privacy_errors << PrivacyError.new(receiver_class, method_name)
@privacy_samples += 1
@privacy_failures += 1
@raise_type |= ClassRegistry['NoMethodError'].as_type
end
|
- (Object) normal_dispatch(method, self_type, cartesian)
92
93
94
95
96
97
98
99
100
101
102
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 92
def normal_dispatch(method, self_type, cartesian)
cartesian.each do |*type_list, block_type|
raise_frequency = method.raise_frequency_for_types(self_type, type_list, block_type)
if raise_frequency > Frequency::NEVER
fails_dispatch(method.raise_type_for_types(self_type, type_list, block_type))
end
if raise_frequency < Frequency::ALWAYS
passes_dispatch(method.return_type_for_types(self_type, type_list, block_type))
end
end
end
|
- (Object) normal_failure_frequency
Calculated dispatch issues ###########
170
171
172
173
174
175
176
177
178
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 170
def normal_failure_frequency
if @normal_failures == 0
Frequency::NEVER
elsif @normal_failures == @normal_samples
Frequency::ALWAYS
else
Frequency::MAYBE
end
end
|
- (Object) passes_arity
134
135
136
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 134
def passes_arity
@arity_samples += 1
end
|
- (Object) passes_dispatch(return_type)
180
181
182
183
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 180
def passes_dispatch(return_type)
@result_type |= return_type
@normal_samples += 1
end
|
- (Object) passes_privacy
157
158
159
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 157
def passes_privacy
@privacy_samples += 1
end
|
- (Object) privacy_failure_frequency
Privacy-related dispatch issues ############
147
148
149
150
151
152
153
154
155
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 147
def privacy_failure_frequency
if @privacy_failures == 0
Frequency::NEVER
elsif @privacy_failures == @privacy_samples
Frequency::ALWAYS
else
Frequency::MAYBE
end
end
|
- (Object) raise_frequency
114
115
116
117
118
119
120
121
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 114
def raise_frequency
if @privacy_samples.zero?
Frequency::ALWAYS
else
[arity_failure_frequency, privacy_failure_frequency,
normal_failure_frequency].max
end
end
|
- (Object) raise_type
Result Accessors ##############
106
107
108
109
110
111
112
|
# File 'lib/laser/analysis/bootstrap/dispatch_results.rb', line 106
def raise_type
if @privacy_samples.zero?
ClassRegistry['NoMethodError'].as_type
else
@raise_type
end
end
|