deep-cover 0.6.2 → 0.6.3.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|