deep-cover 0.6.2 → 0.6.3.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.rspec +2 -1
- data/.rspec_all +2 -1
- data/.rubocop.yml +8 -9
- data/Gemfile +2 -0
- data/Rakefile +32 -6
- data/bin/cov +3 -3
- data/deep_cover.gemspec +3 -16
- data/exe/deep-cover +5 -0
- data/lib/deep_cover/cli/debugger.rb +1 -1
- data/lib/deep_cover/cli/exec.rb +1 -1
- data/lib/deep_cover/cli/instrumented_clone_reporter.rb +5 -3
- data/lib/deep_cover/cli/runner.rb +2 -2
- data/lib/deep_cover/{tools/dump_covered_code.rb → dump_covered_code.rb} +2 -0
- metadata +10 -203
- data/lib/deep-cover.rb +0 -3
- data/lib/deep_cover.rb +0 -22
- data/lib/deep_cover/analyser.rb +0 -23
- data/lib/deep_cover/analyser/base.rb +0 -104
- data/lib/deep_cover/analyser/branch.rb +0 -41
- data/lib/deep_cover/analyser/covered_code_source.rb +0 -21
- data/lib/deep_cover/analyser/function.rb +0 -14
- data/lib/deep_cover/analyser/node.rb +0 -54
- data/lib/deep_cover/analyser/per_char.rb +0 -38
- data/lib/deep_cover/analyser/per_line.rb +0 -41
- data/lib/deep_cover/analyser/ruby25_like_branch.rb +0 -211
- data/lib/deep_cover/analyser/statement.rb +0 -33
- data/lib/deep_cover/analyser/stats.rb +0 -54
- data/lib/deep_cover/analyser/subset.rb +0 -27
- data/lib/deep_cover/auto_run.rb +0 -71
- data/lib/deep_cover/autoload_tracker.rb +0 -215
- data/lib/deep_cover/backports.rb +0 -22
- data/lib/deep_cover/base.rb +0 -117
- data/lib/deep_cover/basics.rb +0 -22
- data/lib/deep_cover/builtin_takeover.rb +0 -10
- data/lib/deep_cover/config.rb +0 -104
- data/lib/deep_cover/config_setter.rb +0 -33
- data/lib/deep_cover/core_ext/autoload_overrides.rb +0 -112
- data/lib/deep_cover/core_ext/coverage_replacement.rb +0 -61
- data/lib/deep_cover/core_ext/exec_callbacks.rb +0 -27
- data/lib/deep_cover/core_ext/instruction_sequence_load_iseq.rb +0 -32
- data/lib/deep_cover/core_ext/load_overrides.rb +0 -19
- data/lib/deep_cover/core_ext/require_overrides.rb +0 -28
- data/lib/deep_cover/coverage.rb +0 -125
- data/lib/deep_cover/coverage/analysis.rb +0 -42
- data/lib/deep_cover/coverage/persistence.rb +0 -84
- data/lib/deep_cover/covered_code.rb +0 -145
- data/lib/deep_cover/custom_requirer.rb +0 -187
- data/lib/deep_cover/flag_comment_associator.rb +0 -68
- data/lib/deep_cover/load.rb +0 -66
- data/lib/deep_cover/memoize.rb +0 -48
- data/lib/deep_cover/module_override.rb +0 -39
- data/lib/deep_cover/node.rb +0 -23
- data/lib/deep_cover/node/arguments.rb +0 -51
- data/lib/deep_cover/node/assignments.rb +0 -273
- data/lib/deep_cover/node/base.rb +0 -155
- data/lib/deep_cover/node/begin.rb +0 -27
- data/lib/deep_cover/node/block.rb +0 -61
- data/lib/deep_cover/node/branch.rb +0 -32
- data/lib/deep_cover/node/case.rb +0 -113
- data/lib/deep_cover/node/collections.rb +0 -31
- data/lib/deep_cover/node/const.rb +0 -12
- data/lib/deep_cover/node/def.rb +0 -40
- data/lib/deep_cover/node/empty_body.rb +0 -32
- data/lib/deep_cover/node/exceptions.rb +0 -79
- data/lib/deep_cover/node/if.rb +0 -73
- data/lib/deep_cover/node/keywords.rb +0 -86
- data/lib/deep_cover/node/literals.rb +0 -100
- data/lib/deep_cover/node/loops.rb +0 -74
- data/lib/deep_cover/node/mixin/can_augment_children.rb +0 -65
- data/lib/deep_cover/node/mixin/check_completion.rb +0 -18
- data/lib/deep_cover/node/mixin/child_can_be_empty.rb +0 -27
- data/lib/deep_cover/node/mixin/executed_after_children.rb +0 -15
- data/lib/deep_cover/node/mixin/execution_location.rb +0 -66
- data/lib/deep_cover/node/mixin/filters.rb +0 -47
- data/lib/deep_cover/node/mixin/flow_accounting.rb +0 -71
- data/lib/deep_cover/node/mixin/has_child.rb +0 -145
- data/lib/deep_cover/node/mixin/has_child_handler.rb +0 -75
- data/lib/deep_cover/node/mixin/has_tracker.rb +0 -46
- data/lib/deep_cover/node/mixin/is_statement.rb +0 -20
- data/lib/deep_cover/node/mixin/rewriting.rb +0 -35
- data/lib/deep_cover/node/mixin/wrapper.rb +0 -15
- data/lib/deep_cover/node/module.rb +0 -66
- data/lib/deep_cover/node/root.rb +0 -20
- data/lib/deep_cover/node/send.rb +0 -161
- data/lib/deep_cover/node/short_circuit.rb +0 -42
- data/lib/deep_cover/node/splat.rb +0 -15
- data/lib/deep_cover/node/variables.rb +0 -16
- data/lib/deep_cover/parser_ext/range.rb +0 -21
- data/lib/deep_cover/problem_with_diagnostic.rb +0 -63
- data/lib/deep_cover/reporter.rb +0 -10
- data/lib/deep_cover/reporter/base.rb +0 -68
- data/lib/deep_cover/reporter/html.rb +0 -15
- data/lib/deep_cover/reporter/html/base.rb +0 -14
- data/lib/deep_cover/reporter/html/index.rb +0 -59
- data/lib/deep_cover/reporter/html/site.rb +0 -70
- data/lib/deep_cover/reporter/html/source.rb +0 -136
- data/lib/deep_cover/reporter/html/template/assets/32px.png +0 -0
- data/lib/deep_cover/reporter/html/template/assets/40px.png +0 -0
- data/lib/deep_cover/reporter/html/template/assets/deep_cover.css.sass +0 -336
- data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.js +0 -4
- data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.map +0 -1
- data/lib/deep_cover/reporter/html/template/assets/jstree.css +0 -1108
- data/lib/deep_cover/reporter/html/template/assets/jstree.js +0 -8424
- data/lib/deep_cover/reporter/html/template/assets/jstreetable.js +0 -1069
- data/lib/deep_cover/reporter/html/template/assets/throbber.gif +0 -0
- data/lib/deep_cover/reporter/html/template/index.html.erb +0 -75
- data/lib/deep_cover/reporter/html/template/source.html.erb +0 -35
- data/lib/deep_cover/reporter/istanbul.rb +0 -184
- data/lib/deep_cover/reporter/text.rb +0 -58
- data/lib/deep_cover/reporter/tree/util.rb +0 -86
- data/lib/deep_cover/tools.rb +0 -22
- data/lib/deep_cover/tools/blank.rb +0 -25
- data/lib/deep_cover/tools/builtin_coverage.rb +0 -55
- data/lib/deep_cover/tools/camelize.rb +0 -13
- data/lib/deep_cover/tools/content_tag.rb +0 -11
- data/lib/deep_cover/tools/covered.rb +0 -9
- data/lib/deep_cover/tools/execute_sample.rb +0 -34
- data/lib/deep_cover/tools/format.rb +0 -18
- data/lib/deep_cover/tools/format_char_cover.rb +0 -19
- data/lib/deep_cover/tools/format_generated_code.rb +0 -27
- data/lib/deep_cover/tools/indent_string.rb +0 -26
- data/lib/deep_cover/tools/merge.rb +0 -16
- data/lib/deep_cover/tools/number_lines.rb +0 -22
- data/lib/deep_cover/tools/our_coverage.rb +0 -11
- data/lib/deep_cover/tools/profiling.rb +0 -68
- data/lib/deep_cover/tools/render_template.rb +0 -13
- data/lib/deep_cover/tools/require_relative_dir.rb +0 -12
- data/lib/deep_cover/tools/scan_match_datas.rb +0 -10
- data/lib/deep_cover/tools/silence_warnings.rb +0 -18
- data/lib/deep_cover/tools/slice.rb +0 -9
- data/lib/deep_cover/tools/strip_heredoc.rb +0 -18
- data/lib/deep_cover/tools/truncate_backtrace.rb +0 -32
- data/lib/deep_cover/tracker_bucket.rb +0 -50
- data/lib/deep_cover/tracker_hits_per_path.rb +0 -35
- data/lib/deep_cover/tracker_storage.rb +0 -76
- data/lib/deep_cover/tracker_storage_per_path.rb +0 -34
- data/lib/deep_cover/version.rb +0 -5
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
module Node::Mixin
|
5
|
-
module HasChildHandler
|
6
|
-
def self.included(base)
|
7
|
-
base.extend ClassMethods
|
8
|
-
end
|
9
|
-
|
10
|
-
def call_child_handler(template, child, child_name = nil)
|
11
|
-
child_name ||= self.child_index_to_name(child.index)
|
12
|
-
method_name = format(template, name: child_name)
|
13
|
-
if respond_to?(method_name)
|
14
|
-
args = [child, child_name]
|
15
|
-
arity = method(method_name).arity
|
16
|
-
if arity >= 0
|
17
|
-
args = args[0...arity]
|
18
|
-
end
|
19
|
-
answer = send(method_name, *args)
|
20
|
-
end
|
21
|
-
answer
|
22
|
-
end
|
23
|
-
private :call_child_handler
|
24
|
-
|
25
|
-
module ClassMethods
|
26
|
-
def has_child_handler(template)
|
27
|
-
child_method_name = format(template, name: 'child')
|
28
|
-
action = template.gsub(/_%{name}/, '').gsub(/%{name}_/, '')
|
29
|
-
const_name = "#{Tools.camelize(action)}Handler"
|
30
|
-
class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
31
|
-
module #{const_name} # module RewriteHandler
|
32
|
-
module ClassMethods # module ClassMethods
|
33
|
-
def has_child(#{action}: nil, **args) # def has_child(rewrite: nil, **args)
|
34
|
-
name, _types = args.first # name, _types = args.first
|
35
|
-
define_child_handler(#{template.inspect}, # define_child_handler('rewrite_%{child}',
|
36
|
-
name, #{action}) # name, rewrite)
|
37
|
-
super(**args) # super(**args)
|
38
|
-
end # end
|
39
|
-
end # end
|
40
|
-
|
41
|
-
def #{child_method_name}(child, name = nil) # def rewrite_child(child, name = nil)
|
42
|
-
call_child_handler(#{template.inspect}, child, # call_child_handler('rewrite_%{child}', child,
|
43
|
-
name) || super # name) || super
|
44
|
-
end # end
|
45
|
-
end # end
|
46
|
-
include #{const_name} # include RewriteHandler
|
47
|
-
singleton_class.prepend #{const_name}::ClassMethods # singleton_class.prepend RewriteHandler::ClassMethods
|
48
|
-
EVAL
|
49
|
-
end
|
50
|
-
|
51
|
-
def define_child_handler(template, name, action)
|
52
|
-
method_name = format(template, name: name)
|
53
|
-
case action
|
54
|
-
when nil
|
55
|
-
# Nothing to do
|
56
|
-
when Symbol
|
57
|
-
define_method(method_name) do |*args|
|
58
|
-
arity = method(action).arity
|
59
|
-
if arity < 0
|
60
|
-
send(action, *args)
|
61
|
-
else
|
62
|
-
send(action, *args[0...arity])
|
63
|
-
end
|
64
|
-
end
|
65
|
-
when Proc
|
66
|
-
define_method(method_name, &action)
|
67
|
-
else
|
68
|
-
define_method(method_name) { |*| action }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
private :define_child_handler
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
module Node::Mixin
|
5
|
-
module HasTracker
|
6
|
-
def self.included(base)
|
7
|
-
base.extend ClassMethods
|
8
|
-
end
|
9
|
-
TRACKERS = {}
|
10
|
-
|
11
|
-
def initialize(*)
|
12
|
-
@tracker_offset = tracker_storage.allocate_trackers(self.class::TRACKERS.size).begin
|
13
|
-
super
|
14
|
-
end
|
15
|
-
|
16
|
-
def tracker_storage
|
17
|
-
covered_code.tracker_storage
|
18
|
-
end
|
19
|
-
|
20
|
-
def tracker_sources
|
21
|
-
self.class::TRACKERS.map do |name, _|
|
22
|
-
[:"#{name}_tracker", send(:"#{name}_tracker_source")]
|
23
|
-
end.to_h
|
24
|
-
end
|
25
|
-
|
26
|
-
module ClassMethods
|
27
|
-
def inherited(base)
|
28
|
-
base.const_set :TRACKERS, self::TRACKERS.dup
|
29
|
-
super
|
30
|
-
end
|
31
|
-
|
32
|
-
def has_tracker(name)
|
33
|
-
i = self::TRACKERS[name] = self::TRACKERS.size
|
34
|
-
class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
35
|
-
def #{name}_tracker_source
|
36
|
-
tracker_storage.tracker_source(@tracker_offset + #{i})
|
37
|
-
end
|
38
|
-
def #{name}_tracker_hits
|
39
|
-
tracker_storage[@tracker_offset + #{i}]
|
40
|
-
end
|
41
|
-
EVAL
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
module Node::Mixin
|
5
|
-
module IsStatement
|
6
|
-
def self.included(base)
|
7
|
-
base.has_child_handler('is_%{name}_statement')
|
8
|
-
end
|
9
|
-
|
10
|
-
def is_statement
|
11
|
-
parent.is_child_statement(self)
|
12
|
-
end
|
13
|
-
|
14
|
-
# Default child rewriting rule
|
15
|
-
def is_child_statement(child, name = nil)
|
16
|
-
:if_incompatible
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
module Node::Mixin
|
5
|
-
module Rewriting
|
6
|
-
def self.included(base)
|
7
|
-
base.has_child_handler('rewrite_%{name}')
|
8
|
-
end
|
9
|
-
|
10
|
-
# Code to add before and after the node for covering purposes
|
11
|
-
def rewrite
|
12
|
-
end
|
13
|
-
|
14
|
-
# Default child rewriting rule
|
15
|
-
def rewrite_child(child, name = nil)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Replaces all the '%{local}' or '%{some_tracker}' in rewriting rules
|
19
|
-
def resolve_rewrite(rule, context)
|
20
|
-
return if rule == nil
|
21
|
-
sources = context.tracker_sources
|
22
|
-
format(rule, local: covered_code.local_var, node: '%{node}', **sources)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Returns an array of [range, rule], where rule is a string containing '%{node}'
|
26
|
-
# Rules must be ordered inner-most first
|
27
|
-
def rewriting_rules
|
28
|
-
[
|
29
|
-
resolve_rewrite(rewrite, self),
|
30
|
-
resolve_rewrite(parent.rewrite_child(self), parent),
|
31
|
-
].compact.map { |rule| [expression, rule] }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'const'
|
4
|
-
|
5
|
-
module DeepCover
|
6
|
-
class Node
|
7
|
-
class ModuleName < Node
|
8
|
-
has_child scope: [Node, nil]
|
9
|
-
has_child const_name: Symbol
|
10
|
-
|
11
|
-
def flow_completion_count
|
12
|
-
parent.execution_count
|
13
|
-
end
|
14
|
-
|
15
|
-
def execution_count
|
16
|
-
if scope
|
17
|
-
scope.flow_completion_count
|
18
|
-
else
|
19
|
-
super
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class Module < Node
|
25
|
-
check_completion
|
26
|
-
has_tracker :body_entry
|
27
|
-
has_child const: {const: ModuleName}
|
28
|
-
has_child body: Node,
|
29
|
-
can_be_empty: -> { base_node.loc.end.begin },
|
30
|
-
rewrite: '%{body_entry_tracker};%{local}=nil;%{node}',
|
31
|
-
is_statement: true,
|
32
|
-
flow_entry_count: :body_entry_tracker_hits
|
33
|
-
executed_loc_keys :keyword
|
34
|
-
|
35
|
-
def execution_count
|
36
|
-
body_entry_tracker_hits
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class Class < Node
|
41
|
-
check_completion
|
42
|
-
has_tracker :body_entry
|
43
|
-
has_child const: {const: ModuleName}
|
44
|
-
has_child inherit: [Node, nil] # TODO
|
45
|
-
has_child body: Node,
|
46
|
-
can_be_empty: -> { base_node.loc.end.begin },
|
47
|
-
rewrite: '%{body_entry_tracker};%{node}',
|
48
|
-
is_statement: true,
|
49
|
-
flow_entry_count: :body_entry_tracker_hits
|
50
|
-
executed_loc_keys :keyword
|
51
|
-
|
52
|
-
def execution_count
|
53
|
-
body_entry_tracker_hits
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# class << foo
|
58
|
-
class Sclass < Node
|
59
|
-
has_child object: Node
|
60
|
-
has_child body: Node,
|
61
|
-
can_be_empty: -> { base_node.loc.end.begin },
|
62
|
-
is_statement: true
|
63
|
-
# TODO
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
data/lib/deep_cover/node/root.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
class Node::Root < Node
|
5
|
-
has_tracker :root
|
6
|
-
has_child main: Node,
|
7
|
-
can_be_empty: -> { Parser::Source::Range.new(covered_code.buffer, 0, 0) },
|
8
|
-
is_statement: true,
|
9
|
-
rewrite: -> {
|
10
|
-
"#{tracker_storage.setup_source};%{root_tracker};%{local}=nil;%{node}"
|
11
|
-
}
|
12
|
-
attr_reader :covered_code
|
13
|
-
alias_method :flow_entry_count, :root_tracker_hits
|
14
|
-
|
15
|
-
def initialize(child_ast, covered_code)
|
16
|
-
@covered_code = covered_code
|
17
|
-
super(nil, parent: nil, base_children: [child_ast])
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/deep_cover/node/send.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'literals'
|
4
|
-
require_relative 'branch'
|
5
|
-
|
6
|
-
module DeepCover
|
7
|
-
class Node
|
8
|
-
class SendBase < Node
|
9
|
-
has_child receiver: [Node, nil]
|
10
|
-
has_child message: Symbol
|
11
|
-
has_extra_children arguments: Node
|
12
|
-
executed_loc_keys :dot, :selector_begin, :selector_end, :operator
|
13
|
-
|
14
|
-
def loc_hash
|
15
|
-
hash = super.dup
|
16
|
-
selector = hash.delete(:selector)
|
17
|
-
|
18
|
-
# Special case for foo[bar]=baz, but not for foo.[]= bar, baz: we split selector into begin and end
|
19
|
-
if base_node.location.dot == nil && [:[], :[]=].include?(message)
|
20
|
-
hash[:selector_begin] = selector.resize(1)
|
21
|
-
hash[:selector_end] = Parser::Source::Range.new(selector.source_buffer, selector.end_pos - 1, selector.end_pos)
|
22
|
-
else
|
23
|
-
hash.delete(:dot) if type == :safe_send # Hack. API to get a Parser::AST::Send::Map without the dot is crappy.
|
24
|
-
hash[:selector_begin] = selector
|
25
|
-
end
|
26
|
-
|
27
|
-
hash
|
28
|
-
end
|
29
|
-
|
30
|
-
# Rules must be ordered inner-most first
|
31
|
-
def rewriting_rules
|
32
|
-
rules = super
|
33
|
-
if need_parentheses?
|
34
|
-
range = arguments.last.expression.with(begin_pos: loc_hash[:selector_begin].end_pos)
|
35
|
-
rules.unshift [range, '(%{node})']
|
36
|
-
end
|
37
|
-
rules
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
# In different circumstances, we need ().
|
43
|
-
# Deal with ambiguous cases where a method is hidden by a local. Ex:
|
44
|
-
# foo 42, 'hello' #=> Works
|
45
|
-
# foo (42), 'hello' #=> Simplification of what DeepCover would generate, still works
|
46
|
-
# foo = 1; foo 42, 'hello' #=> works
|
47
|
-
# foo = 1; foo (42), 'hello' #=> syntax error.
|
48
|
-
# foo = 1; foo((42), 'hello') #=> works
|
49
|
-
# Deal with do/end block. Ex:
|
50
|
-
# x.foo 42, 43 # => ok
|
51
|
-
# x.foo (42), 43 # => ok
|
52
|
-
# x.foo ((42)), 43 # => ok
|
53
|
-
# x.foo 42, 43 do ; end # => ok
|
54
|
-
# x.foo (42), 43 do ; end # => ok
|
55
|
-
# x.foo ((42)), 43 do ; end # => parse error!
|
56
|
-
def need_parentheses?
|
57
|
-
true unless
|
58
|
-
arguments.empty? || # No issue when no arguments
|
59
|
-
loc_hash[:selector_end] || # No issue with foo[bar]= and such
|
60
|
-
loc_hash[:operator] || # No issue with foo.bar=
|
61
|
-
(receiver && !loc_hash[:dot]) || # No issue with foo + bar
|
62
|
-
loc_hash[:begin] # Ok if has parentheses
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
class Send < SendBase
|
67
|
-
check_completion
|
68
|
-
end
|
69
|
-
|
70
|
-
class CsendInnerSend < SendBase
|
71
|
-
has_tracker :completion
|
72
|
-
include ExecutedAfterChildren
|
73
|
-
|
74
|
-
def has_block?
|
75
|
-
parent.has_block?
|
76
|
-
end
|
77
|
-
|
78
|
-
def rewrite
|
79
|
-
# All the rest of the rewriting logic is in Csend
|
80
|
-
'%{node};%{completion_tracker};' unless has_block?
|
81
|
-
end
|
82
|
-
|
83
|
-
def flow_completion_count
|
84
|
-
return parent.parent.flow_completion_count if has_block?
|
85
|
-
completion_tracker_hits
|
86
|
-
end
|
87
|
-
|
88
|
-
def loc_hash
|
89
|
-
# This is only a partial Send, the receiver param and the dot are actually handled by the parent Csend.
|
90
|
-
h = super.dup
|
91
|
-
h[:expression] = h[:expression].with(begin_pos: h[:selector_begin].begin_pos)
|
92
|
-
h
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class Csend < Node
|
97
|
-
# The overall rewriting goal is this:
|
98
|
-
# temp = *receiver*;
|
99
|
-
# if nil != temp
|
100
|
-
# TRACK_my_NOT_NIL
|
101
|
-
# temp = temp&.*actual_send*{block}
|
102
|
-
# TRACK_actual_send_COMPLETION
|
103
|
-
# t
|
104
|
-
# else
|
105
|
-
# nil
|
106
|
-
# end
|
107
|
-
# This is split across the children and the CsendInnerSend
|
108
|
-
include Branch
|
109
|
-
has_tracker :not_nil
|
110
|
-
has_child receiver: Node,
|
111
|
-
rewrite: '(%{local}=%{node};if nil != %{local};%{not_nil_tracker};%{local}=%{local}'
|
112
|
-
REWRITE_SUFFIX = '%{node};%{local};else;nil;end)'
|
113
|
-
|
114
|
-
has_child actual_send: {safe_send: CsendInnerSend},
|
115
|
-
flow_entry_count: :not_nil_tracker_hits
|
116
|
-
|
117
|
-
def initialize(base_node, base_children: base_node.children, **) # rubocop:disable Naming/UncommunicativeMethodParamName [#5436]
|
118
|
-
send_without_receiver = base_node.updated(:safe_send, [nil, *base_node.children.drop(1)])
|
119
|
-
base_children = [base_children.first, send_without_receiver]
|
120
|
-
super
|
121
|
-
end
|
122
|
-
|
123
|
-
executed_loc_keys :dot
|
124
|
-
|
125
|
-
def has_block?
|
126
|
-
parent.is_a?(Block) && parent.child_index_to_name(index) == :call
|
127
|
-
end
|
128
|
-
|
129
|
-
def rewrite
|
130
|
-
REWRITE_SUFFIX unless has_block?
|
131
|
-
end
|
132
|
-
|
133
|
-
def execution_count
|
134
|
-
receiver.flow_completion_count
|
135
|
-
end
|
136
|
-
|
137
|
-
def message
|
138
|
-
actual_send.message
|
139
|
-
end
|
140
|
-
|
141
|
-
def branches
|
142
|
-
[TrivialBranch.new(condition: receiver, other_branch: actual_send),
|
143
|
-
actual_send,
|
144
|
-
]
|
145
|
-
end
|
146
|
-
|
147
|
-
def branches_summary(of_branches = branches)
|
148
|
-
of_branches.map do |jump|
|
149
|
-
jump == actual_send ? 'safe send' : 'nil shortcut'
|
150
|
-
end.join(' and ')
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
class MatchWithLvasgn < Node
|
155
|
-
check_completion
|
156
|
-
has_child receiver: Regexp
|
157
|
-
has_child compare_to: Node
|
158
|
-
# TODO: test
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|