deep-cover 0.1.13 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/bin/test_gems +2 -1
- data/bin/testall +0 -1
- data/lib/deep_cover.rb +2 -0
- data/lib/deep_cover/analyser/base.rb +7 -1
- data/lib/deep_cover/analyser/per_char.rb +1 -1
- data/lib/deep_cover/analyser/per_line.rb +1 -1
- data/lib/deep_cover/cli/debugger.rb +0 -2
- data/lib/deep_cover/cli/deep_cover.rb +2 -1
- data/lib/deep_cover/cli/instrumented_clone_reporter.rb +74 -25
- data/lib/deep_cover/coverage.rb +5 -2
- data/lib/deep_cover/covered_code.rb +7 -4
- data/lib/deep_cover/node/base.rb +31 -3
- data/lib/deep_cover/node/mixin/execution_location.rb +4 -0
- data/lib/deep_cover/node/mixin/flow_accounting.rb +5 -0
- data/lib/deep_cover/node/send.rb +11 -2
- data/lib/deep_cover/problem_with_diagnostic.rb +61 -0
- data/lib/deep_cover/tools/number_lines.rb +2 -0
- data/lib/deep_cover/tools/our_coverage.rb +1 -1
- data/lib/deep_cover/tools/truncate_backtrace.rb +30 -0
- data/lib/deep_cover/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6de45ce3979398ef5abb25a8147848ad13fa370
|
4
|
+
data.tar.gz: 74dfa0b7b03271419f0b2c7094e124b447392c46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a455c059204f7eeb91f57ca3d4453a7a79021ece85e3228b4a312034dcaef7d022f0776dc9179bcb1dc44049971ba5248fcdc94badcacc6ab1c08bbd9da195e
|
7
|
+
data.tar.gz: 8c6ec4f7204c95968a329d1ae3896cf9c0e41c68973883add1beca6d1efdcdba353e09ff11dfa97651488a75e2cb4f6dd7cc70d5f23159b21efaba6e967233e4
|
data/Rakefile
CHANGED
@@ -14,6 +14,7 @@ namespace :dev do
|
|
14
14
|
if RUBY_VERSION >= '2.2.2' && (!defined?(RUBY_ENGINE) || RUBY_ENGINE != 'jruby')
|
15
15
|
commands << 'bundle install --gemfile=spec/full_usage/rails51_project/Gemfile'
|
16
16
|
end
|
17
|
+
commands << 'bundle install --gemfile=spec/cli_fixtures/simple_rails42_app/Gemfile'
|
17
18
|
|
18
19
|
commands.each do |command|
|
19
20
|
puts "Running: #{command}"
|
data/bin/test_gems
CHANGED
@@ -8,7 +8,8 @@ def gem_list
|
|
8
8
|
rspec-support thread_safe rspec-core rspec-expectations rspec-mocks rspec mini_portile
|
9
9
|
multi_json rspec-support rspec-expectations rspec-mocks mail nokogiri rack rspec unf
|
10
10
|
json thread_safe rspec-core json rack-protection sdoc docile faraday multi_xml coderay
|
11
|
-
mime-types net-scp multi_json turbolinks formatador coffee-script rack-test]
|
11
|
+
mime-types net-scp multi_json turbolinks formatador coffee-script rack-test] +
|
12
|
+
%w[devise]
|
12
13
|
# How I got those:
|
13
14
|
require 'gems'
|
14
15
|
Gems.most_downloaded
|
data/bin/testall
CHANGED
data/lib/deep_cover.rb
CHANGED
@@ -33,7 +33,13 @@ module DeepCover
|
|
33
33
|
def each_node(from = covered_code.root, &block)
|
34
34
|
return to_enum(:each_node) unless block_given?
|
35
35
|
children = node_children(from)
|
36
|
-
|
36
|
+
begin
|
37
|
+
yield from, children unless from.is_a?(Node::Root)
|
38
|
+
rescue ProblemWithDiagnostic
|
39
|
+
raise
|
40
|
+
rescue StandardError, SystemStackError => e
|
41
|
+
raise ProblemWithDiagnostic.new(covered_code, from.diagnostic_expression, e)
|
42
|
+
end
|
37
43
|
children.each do |child|
|
38
44
|
each_node(child, &block)
|
39
45
|
end
|
@@ -9,7 +9,7 @@ module DeepCover
|
|
9
9
|
runs = node_runs(node)
|
10
10
|
if runs != nil
|
11
11
|
node.proper_range.each do |pos|
|
12
|
-
bc[buffer.line_for_position(pos)-
|
12
|
+
bc[buffer.line_for_position(pos)-buffer.first_line][buffer.column_for_position(pos)] = runs > 0 ? ' ' : 'x'
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -3,7 +3,7 @@ module DeepCover
|
|
3
3
|
# Returns an array of runs, one per line.
|
4
4
|
def results
|
5
5
|
disallow_partial = !options.fetch(:allow_partial, true)
|
6
|
-
line_hits = Array.new(covered_code.nb_lines)
|
6
|
+
line_hits = Array.new(covered_code.nb_lines + covered_code.lineno - 1)
|
7
7
|
each_node do |node, _children|
|
8
8
|
if (runs = node_runs(node))
|
9
9
|
node.executed_locs.each do |loc|
|
@@ -37,8 +37,9 @@ module DeepCover
|
|
37
37
|
o.banner = "usage: deep-cover [options] [path/to/app/or/gem]"
|
38
38
|
o.separator ''
|
39
39
|
o.string '-o', '--output', 'output folder', default: './coverage'
|
40
|
-
o.string '-c', '--command', 'command to run tests', default: 'rake'
|
40
|
+
o.string '-c', '--command', 'command to run tests', default: 'bundle exec rake'
|
41
41
|
o.bool '--bundle', 'run bundle before the tests', default: true
|
42
|
+
o.bool '--process', 'turn off to only redo the reporting', default: true
|
42
43
|
o.separator 'Coverage options'
|
43
44
|
@ignore_uncovered_map = Analyser.optionally_covered.map do |option|
|
44
45
|
default = Config::DEFAULTS[:ignore_uncovered].include?(option)
|
@@ -8,10 +8,10 @@ module DeepCover
|
|
8
8
|
# matches regular files, .files, ..files, but not '.' or '..'
|
9
9
|
GLOB_ALL_CONTENT = '{,.[^.],..?}*'
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(source_path, command: 'rake', **options)
|
12
12
|
@command = command
|
13
13
|
@options = options
|
14
|
-
@root_path =
|
14
|
+
@root_path = @source_path = Pathname.new(source_path).expand_path
|
15
15
|
unless @root_path.join('Gemfile').exist?
|
16
16
|
# E.g. rails/activesupport
|
17
17
|
@root_path = @root_path.dirname
|
@@ -20,40 +20,85 @@ module DeepCover
|
|
20
20
|
@dest_root = Pathname('~/test_deep_cover').expand_path
|
21
21
|
@dest_root = Pathname.new(Dir.mktmpdir("deep_cover_test")) unless @dest_root.exist?
|
22
22
|
|
23
|
-
|
24
|
-
gem_relative_path = gem_path.relative_path_from(@root_path)
|
23
|
+
gem_relative_path = @source_path.relative_path_from(@root_path)
|
25
24
|
@main_path = @dest_root.join(gem_relative_path)
|
25
|
+
singleton_class.include self.class.const_get(Tools.camelize(style))
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear
|
29
|
+
FileUtils.rm_rf(Dir.glob("#{@dest_root}/#{GLOB_ALL_CONTENT}"))
|
26
30
|
end
|
27
31
|
|
28
32
|
def copy
|
29
33
|
return true if @copied
|
34
|
+
puts "Cloning..."
|
30
35
|
FileUtils.cp_r(Dir.glob("#{@root_path}/#{GLOB_ALL_CONTENT}"), @dest_root)
|
31
36
|
@copied = true
|
32
37
|
end
|
33
38
|
|
34
39
|
def patch_ruby_file(ruby_file)
|
35
|
-
content =
|
40
|
+
content = ruby_file.read
|
36
41
|
# Insert our code after leading comments:
|
37
42
|
content.sub!(/^((#.*\n+)*)/, "#{$1}require 'deep_cover/auto_run';DeepCover::AutoRun.run! '#{@dest_root}';")
|
38
|
-
|
43
|
+
ruby_file.write(content)
|
39
44
|
end
|
40
45
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
46
|
+
def style
|
47
|
+
if @source_path.join('config/environments/test.rb').exist?
|
48
|
+
:rails
|
49
|
+
elsif @source_path.join('lib').exist?
|
50
|
+
:single_gem
|
45
51
|
else # Rails style
|
52
|
+
:gem_collection
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Style specific functionality
|
57
|
+
module Gem
|
58
|
+
def each_main_ruby_files(&block)
|
59
|
+
each_gem_path do |dest_path|
|
60
|
+
main = dest_path.join('lib/*.rb')
|
61
|
+
Pathname.glob(main).select(&:file?).each(&block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def each_dir_to_cover
|
66
|
+
each_gem_path do |dest_path|
|
67
|
+
yield dest_path.join('lib')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
module SingleGem
|
73
|
+
include Gem
|
74
|
+
def each_gem_path
|
75
|
+
yield @main_path
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module GemCollection
|
80
|
+
include Gem
|
81
|
+
def each_gem_path
|
46
82
|
Pathname.glob(@main_path.join('*/lib')).each{|p| yield p.dirname}
|
47
83
|
end
|
48
84
|
end
|
49
85
|
|
86
|
+
module Rails
|
87
|
+
def each_main_ruby_files
|
88
|
+
yield @main_path.join('config/environments/test.rb')
|
89
|
+
end
|
90
|
+
|
91
|
+
def each_dir_to_cover
|
92
|
+
yield @main_path.join('app')
|
93
|
+
yield @main_path.join('lib')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Back to global functionality
|
50
98
|
def patch_main_ruby_files
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
puts "Patching #{main}"
|
55
|
-
patch_ruby_file(main)
|
56
|
-
end
|
99
|
+
each_main_ruby_files do |main|
|
100
|
+
puts "Patching #{main}"
|
101
|
+
patch_ruby_file(main)
|
57
102
|
end
|
58
103
|
end
|
59
104
|
|
@@ -88,11 +133,12 @@ module DeepCover
|
|
88
133
|
|
89
134
|
def cover
|
90
135
|
coverage = Coverage.new
|
91
|
-
|
92
|
-
|
93
|
-
|
136
|
+
each_dir_to_cover do |to_cover|
|
137
|
+
original = to_cover.sub_ext('_original')
|
138
|
+
FileUtils.cp_r(to_cover, original)
|
139
|
+
Tools.dump_covered_code(original,
|
94
140
|
coverage: coverage, root_path: @dest_root.to_s,
|
95
|
-
dest_path:
|
141
|
+
dest_path: to_cover)
|
96
142
|
end
|
97
143
|
coverage.save(@dest_root.to_s)
|
98
144
|
end
|
@@ -116,11 +162,14 @@ module DeepCover
|
|
116
162
|
end
|
117
163
|
|
118
164
|
def run
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
165
|
+
if @options.fetch(:process, true)
|
166
|
+
clear
|
167
|
+
copy
|
168
|
+
cover
|
169
|
+
patch
|
170
|
+
bundle if @options.fetch(:bundle, true)
|
171
|
+
process
|
172
|
+
end
|
124
173
|
report
|
125
174
|
end
|
126
175
|
end
|
data/lib/deep_cover/coverage.rb
CHANGED
@@ -3,7 +3,6 @@ module DeepCover
|
|
3
3
|
silence_warnings do
|
4
4
|
require 'parser/current'
|
5
5
|
end
|
6
|
-
require 'pry'
|
7
6
|
require_relative 'covered_code'
|
8
7
|
require 'securerandom'
|
9
8
|
|
@@ -133,11 +132,15 @@ module DeepCover
|
|
133
132
|
|
134
133
|
def save_trackers(global)
|
135
134
|
saved?
|
135
|
+
trackers = eval(global)
|
136
|
+
# Some testing involves more than one process, some of which don't run any of our covered code.
|
137
|
+
# Don't save anything if that's the case
|
138
|
+
return if trackers.nil?
|
136
139
|
basename = TRACKER_TEMPLATE % {unique: SecureRandom.urlsafe_base64}
|
137
140
|
dir_path.join(basename).binwrite(Marshal.dump({
|
138
141
|
version: DeepCover::VERSION,
|
139
142
|
global: global,
|
140
|
-
trackers:
|
143
|
+
trackers: trackers,
|
141
144
|
}))
|
142
145
|
end
|
143
146
|
|
@@ -6,12 +6,11 @@ module DeepCover
|
|
6
6
|
@@counter = 0
|
7
7
|
@@globals = Hash.new{|h, global| h[global] = eval("#{global} ||= {}") }
|
8
8
|
|
9
|
-
def initialize(path: nil, source: nil, lineno:
|
9
|
+
def initialize(path: nil, source: nil, lineno: 1, tracker_global: DEFAULT_TRACKER_GLOBAL, local_var: '_temp', name: nil)
|
10
10
|
raise "Must provide either path or source" unless path || source
|
11
11
|
|
12
|
-
@buffer = ::Parser::Source::Buffer.new(path)
|
12
|
+
@buffer = ::Parser::Source::Buffer.new(path, lineno)
|
13
13
|
@buffer.source = source ||= File.read(path)
|
14
|
-
@lineno = lineno
|
15
14
|
@tracker_count = 0
|
16
15
|
@tracker_global = tracker_global
|
17
16
|
@local_var = local_var
|
@@ -23,6 +22,10 @@ module DeepCover
|
|
23
22
|
@buffer.name || "(source: '#{@buffer.source[0..20]}...')"
|
24
23
|
end
|
25
24
|
|
25
|
+
def lineno
|
26
|
+
@buffer.first_line
|
27
|
+
end
|
28
|
+
|
26
29
|
def nb_lines
|
27
30
|
@nb_lines ||= begin
|
28
31
|
lines = buffer.source_lines
|
@@ -37,7 +40,7 @@ module DeepCover
|
|
37
40
|
def execute_code(binding: DeepCover::GLOBAL_BINDING.dup)
|
38
41
|
return if has_executed?
|
39
42
|
global[nb] = Array.new(@tracker_count, 0)
|
40
|
-
eval(@covered_source, binding, @buffer.name || '<raw_code>',
|
43
|
+
eval(@covered_source, binding, @buffer.name || '<raw_code>', lineno)
|
41
44
|
self
|
42
45
|
end
|
43
46
|
|
data/lib/deep_cover/node/base.rb
CHANGED
@@ -30,9 +30,38 @@ module DeepCover
|
|
30
30
|
|
31
31
|
### Public API
|
32
32
|
|
33
|
+
# Search self and descendants for a particular Class or type
|
34
|
+
def find_all(lookup)
|
35
|
+
case lookup
|
36
|
+
when ::Class
|
37
|
+
each_node.grep(lookup)
|
38
|
+
when ::Symbol
|
39
|
+
each_node.find_all{|n| n.type == lookup}
|
40
|
+
when ::String
|
41
|
+
each_node.find_all{|n| n.source == lookup}
|
42
|
+
when ::Regexp
|
43
|
+
each_node.find_all{|n| n.source =~ lookup}
|
44
|
+
else
|
45
|
+
binding.pry
|
46
|
+
raise ::TypeError, "Expected class or symbol, got #{lookup.class}: #{lookup.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
33
50
|
# Shortcut to access children
|
34
51
|
def [](v)
|
35
|
-
|
52
|
+
if v.is_a?(Integer)
|
53
|
+
children.fetch(v)
|
54
|
+
else
|
55
|
+
found = find_all(v)
|
56
|
+
case found.size
|
57
|
+
when 1
|
58
|
+
found.first
|
59
|
+
when 0
|
60
|
+
raise "No children of type #{v}"
|
61
|
+
else
|
62
|
+
raise "Ambiguous lookup #{v}, found #{found}."
|
63
|
+
end
|
64
|
+
end
|
36
65
|
end
|
37
66
|
|
38
67
|
# Shortcut to create a node from source code
|
@@ -106,7 +135,6 @@ module DeepCover
|
|
106
135
|
|
107
136
|
private
|
108
137
|
def diagnose(exception)
|
109
|
-
exp = base_node.loc.expression
|
110
138
|
msg = if self.class == Node
|
111
139
|
"Unknown node type encountered: #{base_node.type}"
|
112
140
|
else
|
@@ -116,7 +144,7 @@ module DeepCover
|
|
116
144
|
'Attempting to continue, but this node will not be handled properly',
|
117
145
|
('Its subnodes will be ignored' if children.empty?),
|
118
146
|
'Source:',
|
119
|
-
|
147
|
+
expression,
|
120
148
|
"Original exception:",
|
121
149
|
exception.inspect,
|
122
150
|
].join("\n")
|
@@ -49,6 +49,10 @@ module DeepCover
|
|
49
49
|
expression.source if expression
|
50
50
|
end
|
51
51
|
|
52
|
+
def diagnostic_expression
|
53
|
+
expression || parent.diagnostic_expression
|
54
|
+
end
|
55
|
+
|
52
56
|
# Returns an array of character numbers (in the original buffer) that
|
53
57
|
# pertain exclusively to this node (and thus not to any children).
|
54
58
|
def proper_range
|
data/lib/deep_cover/node/send.rb
CHANGED
@@ -37,16 +37,25 @@ module DeepCover
|
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
-
#
|
40
|
+
# In different circumstances, we need ().
|
41
|
+
# Deal with ambiguous cases where a method is hidden by a local. Ex:
|
41
42
|
# foo 42, 'hello' #=> Works
|
42
43
|
# foo (42), 'hello' #=> Simplification of what DeepCover would generate, still works
|
43
44
|
# foo = 1; foo 42, 'hello' #=> works
|
44
45
|
# foo = 1; foo (42), 'hello' #=> syntax error.
|
45
46
|
# foo = 1; foo((42), 'hello') #=> works
|
47
|
+
# Deal with do/end block. Ex:
|
48
|
+
# x.foo 42, 43 # => ok
|
49
|
+
# x.foo (42), 43 # => ok
|
50
|
+
# x.foo ((42)), 43 # => ok
|
51
|
+
# x.foo 42, 43 do ; end # => ok
|
52
|
+
# x.foo (42), 43 do ; end # => ok
|
53
|
+
# x.foo ((42)), 43 do ; end # => parse error!
|
46
54
|
def need_parentheses?
|
47
55
|
true unless
|
48
56
|
arguments.empty? || # No issue when no arguments
|
49
|
-
|
57
|
+
loc_hash[:selector_end] || # No issue with foo[bar]= and such
|
58
|
+
loc_hash[:operator] || # No issue with foo.bar=
|
50
59
|
loc_hash[:begin] # Ok if has parentheses
|
51
60
|
end
|
52
61
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module DeepCover
|
2
|
+
class ProblemWithDiagnostic < StandardError
|
3
|
+
attr_reader :covered_code, :line_range, :original_exception
|
4
|
+
|
5
|
+
def initialize(covered_code, line_range, original_exception=nil)
|
6
|
+
@covered_code = covered_code
|
7
|
+
if line_range.is_a?(Parser::Source::Range)
|
8
|
+
@line_range = line_range.line..line_range.last_line
|
9
|
+
else
|
10
|
+
@line_range = line_range
|
11
|
+
end
|
12
|
+
@original_exception = original_exception
|
13
|
+
end
|
14
|
+
|
15
|
+
def message
|
16
|
+
msg = []
|
17
|
+
msg << "You found a problem with DeepCover!"
|
18
|
+
msg << "Please open an issue at https://github.com/deep-cover/deep-cover/issues"
|
19
|
+
msg << "and include the following diagnostic information:"
|
20
|
+
extra = begin
|
21
|
+
diagnostic_information_lines.map{|line| "| #{line}"}
|
22
|
+
rescue ProblemWithDiagnostic
|
23
|
+
["Oh no! We're in deep trouble!!!"]
|
24
|
+
rescue Exception => e
|
25
|
+
["Oh no! Even diagnostics are failing: #{e}\n#{e.backtrace}"]
|
26
|
+
end
|
27
|
+
msg.concat(extra)
|
28
|
+
msg.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def diagnostic_information_lines
|
32
|
+
lines = []
|
33
|
+
lines << "Source file: #{covered_code.path}"
|
34
|
+
lines << "Line numbers: #{line_range}"
|
35
|
+
lines << "Source lines around location:"
|
36
|
+
lines.concat source_lines.map{|line| " #{line}" }
|
37
|
+
if original_exception
|
38
|
+
lines << "Original exception:"
|
39
|
+
lines << " #{original_exception.class.name}: #{original_exception.message}"
|
40
|
+
backtrace = Tools.truncate_backtrace(original_exception)
|
41
|
+
lines.concat backtrace.map{|line| " #{line}"}
|
42
|
+
end
|
43
|
+
lines
|
44
|
+
end
|
45
|
+
|
46
|
+
def source_lines(nb_context_line: 7)
|
47
|
+
first_index = line_range.begin - nb_context_line - buffer.first_line
|
48
|
+
first_index = 0 if first_index < 0
|
49
|
+
last_index = line_range.end + nb_context_line - buffer.first_line
|
50
|
+
last_index = 0 if last_index < 0
|
51
|
+
|
52
|
+
lines = buffer.source_lines[first_index..last_index]
|
53
|
+
|
54
|
+
Tools.number_lines(lines, lineno: buffer.first_line, bad_linenos: line_range.to_a)
|
55
|
+
end
|
56
|
+
|
57
|
+
def buffer
|
58
|
+
covered_code.buffer
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -7,8 +7,10 @@ module DeepCover
|
|
7
7
|
cur_lineno = lineno + i
|
8
8
|
cur_lineno_s = cur_lineno.to_s.rjust(nb_lineno_digits)
|
9
9
|
if bad_linenos.include?(cur_lineno)
|
10
|
+
cur_lineno_s = "*#{cur_lineno_s}" unless bad_linenos.empty?
|
10
11
|
prefix = Term::ANSIColor.red("#{cur_lineno_s} | ")
|
11
12
|
else
|
13
|
+
cur_lineno_s = " #{cur_lineno_s}" unless bad_linenos.empty?
|
12
14
|
prefix = Term::ANSIColor.white("#{cur_lineno_s} | ")
|
13
15
|
end
|
14
16
|
"#{prefix}#{line}"
|
@@ -3,7 +3,7 @@ module DeepCover
|
|
3
3
|
def our_coverage(source, fn, lineno, **options)
|
4
4
|
covered_code = CoveredCode.new(source:source, path: fn, lineno: lineno)
|
5
5
|
Tools.execute_sample(covered_code)
|
6
|
-
covered_code.line_coverage(options)
|
6
|
+
covered_code.line_coverage(options)[(lineno-1)..-1]
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DeepCover
|
2
|
+
module Tools::TruncateBacktrace
|
3
|
+
def truncate_backtrace(backtrace, extra_context: 10)
|
4
|
+
backtrace = backtrace.backtrace if backtrace.is_a?(Exception)
|
5
|
+
trace_lines = backtrace.uniq
|
6
|
+
|
7
|
+
keep_from_begin = 0
|
8
|
+
keep_from_end = backtrace.size - 1
|
9
|
+
|
10
|
+
trace_lines.each do |line|
|
11
|
+
from_begin = backtrace.index(line)
|
12
|
+
from_end = backtrace.rindex(line)
|
13
|
+
if from_begin <= backtrace.size - 1 - from_end
|
14
|
+
keep_from_begin = [keep_from_begin, from_begin].max
|
15
|
+
else
|
16
|
+
keep_from_end = [keep_from_end, from_end].min
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
keep_from_begin += extra_context
|
21
|
+
keep_from_end -= extra_context
|
22
|
+
|
23
|
+
return backtrace if keep_from_begin + 5 >= keep_from_end
|
24
|
+
|
25
|
+
result = backtrace[0..keep_from_begin]
|
26
|
+
result << "... #{keep_from_end - keep_from_begin - 1} levels..."
|
27
|
+
result.concat backtrace[keep_from_end..-1]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/deep_cover/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep-cover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc-André Lafortune
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-11-
|
12
|
+
date: 2017-11-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parser
|
@@ -288,6 +288,7 @@ files:
|
|
288
288
|
- lib/deep_cover/node/splat.rb
|
289
289
|
- lib/deep_cover/node/variables.rb
|
290
290
|
- lib/deep_cover/parser_ext/range.rb
|
291
|
+
- lib/deep_cover/problem_with_diagnostic.rb
|
291
292
|
- lib/deep_cover/reporter.rb
|
292
293
|
- lib/deep_cover/reporter/istanbul.rb
|
293
294
|
- lib/deep_cover/tools.rb
|
@@ -304,6 +305,7 @@ files:
|
|
304
305
|
- lib/deep_cover/tools/require_relative_dir.rb
|
305
306
|
- lib/deep_cover/tools/silence_warnings.rb
|
306
307
|
- lib/deep_cover/tools/slice.rb
|
308
|
+
- lib/deep_cover/tools/truncate_backtrace.rb
|
307
309
|
- lib/deep_cover/version.rb
|
308
310
|
homepage: http://github.com
|
309
311
|
licenses:
|
@@ -325,7 +327,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
325
327
|
version: '0'
|
326
328
|
requirements: []
|
327
329
|
rubyforge_project:
|
328
|
-
rubygems_version: 2.6.
|
330
|
+
rubygems_version: 2.6.14
|
329
331
|
signing_key:
|
330
332
|
specification_version: 4
|
331
333
|
summary: Write a short summary, because Rubygems requires one.
|