spoom 1.1.11 → 1.1.12
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/Gemfile +1 -0
- data/README.md +6 -0
- data/Rakefile +1 -0
- data/lib/spoom/cli/bump.rb +11 -7
- data/lib/spoom/cli/coverage.rb +11 -7
- data/lib/spoom/cli/helper.rb +5 -4
- data/lib/spoom/cli/lsp.rb +2 -1
- data/lib/spoom/cli/run.rb +16 -6
- data/lib/spoom/cli.rb +6 -4
- data/lib/spoom/context.rb +219 -0
- data/lib/spoom/coverage/d3/base.rb +12 -8
- data/lib/spoom/coverage/d3/circle_map.rb +40 -37
- data/lib/spoom/coverage/d3/pie.rb +30 -26
- data/lib/spoom/coverage/d3/timeline.rb +86 -82
- data/lib/spoom/coverage/d3.rb +72 -70
- data/lib/spoom/coverage/report.rb +6 -6
- data/lib/spoom/coverage/snapshot.rb +40 -33
- data/lib/spoom/coverage.rb +84 -81
- data/lib/spoom/file_tree.rb +2 -0
- data/lib/spoom/git.rb +107 -97
- data/lib/spoom/printer.rb +4 -0
- data/lib/spoom/sorbet/errors.rb +29 -11
- data/lib/spoom/sorbet/lsp/base.rb +1 -1
- data/lib/spoom/sorbet/lsp/errors.rb +23 -17
- data/lib/spoom/sorbet/lsp/structures.rb +85 -54
- data/lib/spoom/sorbet/lsp.rb +71 -63
- data/lib/spoom/sorbet/metrics.rb +18 -16
- data/lib/spoom/sorbet/sigils.rb +59 -54
- data/lib/spoom/sorbet.rb +11 -8
- data/lib/spoom/timeline.rb +1 -0
- data/lib/spoom/version.rb +1 -1
- data/lib/spoom.rb +43 -25
- metadata +20 -20
- data/lib/spoom/test_helpers/project.rb +0 -138
@@ -18,34 +18,38 @@ module Spoom
|
|
18
18
|
@title = title
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
<<~CSS
|
24
|
-
.pie .title {
|
25
|
-
font: 18px Arial, sans-serif;
|
26
|
-
font-weight: bold;
|
27
|
-
fill: #212529;
|
28
|
-
text-anchor: middle;
|
29
|
-
pointer-events: none;
|
30
|
-
}
|
21
|
+
class << self
|
22
|
+
extend T::Sig
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
24
|
+
sig { returns(String) }
|
25
|
+
def header_style
|
26
|
+
<<~CSS
|
27
|
+
.pie .title {
|
28
|
+
font: 18px Arial, sans-serif;
|
29
|
+
font-weight: bold;
|
30
|
+
fill: #212529;
|
31
|
+
text-anchor: middle;
|
32
|
+
pointer-events: none;
|
33
|
+
}
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
35
|
+
.pie .arc {
|
36
|
+
stroke: #fff;
|
37
|
+
stroke-width: 2px;
|
38
|
+
}
|
39
|
+
CSS
|
40
|
+
end
|
41
|
+
|
42
|
+
sig { returns(String) }
|
43
|
+
def header_script
|
44
|
+
<<~JS
|
45
|
+
function tooltipPie(d, title, kind, sum) {
|
46
|
+
moveTooltip(d)
|
47
|
+
.html("<b>" + title + "</b><br><br>"
|
48
|
+
+ "<b>" + d.data.value + "</b> " + kind + "<br>"
|
49
|
+
+ "<b>" + toPercent(d.data.value, sum) + "</b>%")
|
50
|
+
}
|
51
|
+
JS
|
52
|
+
end
|
49
53
|
end
|
50
54
|
|
51
55
|
sig { override.returns(String) }
|
@@ -18,79 +18,83 @@ module Spoom
|
|
18
18
|
@keys = keys
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
<<~CSS
|
24
|
-
.domain {
|
25
|
-
stroke: transparent;
|
26
|
-
}
|
21
|
+
class << self
|
22
|
+
extend T::Sig
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
sig { returns(String) }
|
25
|
+
def header_style
|
26
|
+
<<~CSS
|
27
|
+
.domain {
|
28
|
+
stroke: transparent;
|
29
|
+
}
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
text-anchor: right;
|
36
|
-
pointer-events: none;
|
37
|
-
}
|
31
|
+
.grid line {
|
32
|
+
stroke: #ccc;
|
33
|
+
}
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
.axis text {
|
36
|
+
font: 12px Arial, sans-serif;
|
37
|
+
fill: #333;
|
38
|
+
text-anchor: right;
|
39
|
+
pointer-events: none;
|
40
|
+
}
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
}
|
42
|
+
.area {
|
43
|
+
fill-opacity: 0.5;
|
44
|
+
}
|
47
45
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
.line {
|
47
|
+
stroke-width: 2;
|
48
|
+
fill: transparent;
|
49
|
+
}
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
.dot {
|
52
|
+
r: 2;
|
53
|
+
fill: #888;
|
54
|
+
}
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
.inverted .grid line {
|
57
|
+
stroke: #777;
|
58
|
+
}
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
.inverted .area {
|
61
|
+
fill-opacity: 0.9;
|
62
|
+
}
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
.inverted .axis text {
|
65
|
+
fill: #fff;
|
66
|
+
}
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
CSS
|
73
|
-
end
|
68
|
+
.inverted .axis line {
|
69
|
+
stroke: #fff;
|
70
|
+
}
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
<<~JS
|
78
|
-
var parseVersion = function(version) {
|
79
|
-
if (!version) {
|
80
|
-
return null;
|
72
|
+
.inverted .dot {
|
73
|
+
fill: #fff;
|
81
74
|
}
|
82
|
-
|
83
|
-
|
75
|
+
CSS
|
76
|
+
end
|
84
77
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
78
|
+
sig { returns(String) }
|
79
|
+
def header_script
|
80
|
+
<<~JS
|
81
|
+
var parseVersion = function(version) {
|
82
|
+
if (!version) {
|
83
|
+
return null;
|
84
|
+
}
|
85
|
+
return parseFloat(version.replaceAll("0.", ""));
|
86
|
+
}
|
87
|
+
|
88
|
+
function tooltipTimeline(d, kind) {
|
89
|
+
moveTooltip(d)
|
90
|
+
.html("commit <b>" + d.data.commit + "</b><br>"
|
91
|
+
+ d3.timeFormat("%y/%m/%d")(parseDate(d.data.timestamp)) + "<br><br>"
|
92
|
+
+ "<b>typed: " + d.key + "</b><br><br>"
|
93
|
+
+ "<b>" + (d.data.values[d.key] ? d.data.values[d.key] : 0) + "</b> " + kind +"<br>"
|
94
|
+
+ "<b>" + toPercent(d.data.values[d.key] ? d.data.values[d.key] : 0, d.data.total) + "%")
|
95
|
+
}
|
96
|
+
JS
|
97
|
+
end
|
94
98
|
end
|
95
99
|
|
96
100
|
sig { override.returns(String) }
|
@@ -264,13 +268,13 @@ module Spoom
|
|
264
268
|
d3.min(data_#{id}, (d) => parseVersion(d.runtime))]) - 0.01",
|
265
269
|
max: "d3.max([d3.max(data_#{id}, (d) => parseVersion(d.static)),
|
266
270
|
d3.max(data_#{id}, (d) => parseVersion(d.runtime))]) + 0.01",
|
267
|
-
ticks:
|
271
|
+
ticks: "ticks(8)"
|
268
272
|
)}
|
269
|
-
#{line(y:
|
270
|
-
#{line(y:
|
271
|
-
#{points(y:
|
273
|
+
#{line(y: "parseVersion(d.runtime)", color: "#e83e8c", curve: "curveStepAfter")}
|
274
|
+
#{line(y: "parseVersion(d.static)", color: "#007bff", curve: "curveStepAfter")}
|
275
|
+
#{points(y: "parseVersion(d.static)")}
|
272
276
|
#{x_ticks}
|
273
|
-
#{y_ticks(ticks:
|
277
|
+
#{y_ticks(ticks: "ticks(4)", format: "'v0.' + d.toFixed(2)", padding: 50)}
|
274
278
|
JS
|
275
279
|
end
|
276
280
|
end
|
@@ -308,15 +312,15 @@ module Spoom
|
|
308
312
|
<<~JS
|
309
313
|
#{x_scale}
|
310
314
|
#{y_scale(
|
311
|
-
min:
|
315
|
+
min: "0",
|
312
316
|
max: "d3.max(data_#{id}, (d) => d.runtime)",
|
313
|
-
ticks:
|
317
|
+
ticks: "ticks(10)"
|
314
318
|
)}
|
315
|
-
#{area(y:
|
316
|
-
#{line(y:
|
317
|
-
#{points(y:
|
319
|
+
#{area(y: "d.runtime")}
|
320
|
+
#{line(y: "d.runtime")}
|
321
|
+
#{points(y: "d.runtime")}
|
318
322
|
#{x_ticks}
|
319
|
-
#{y_ticks(ticks:
|
323
|
+
#{y_ticks(ticks: "ticks(5)", format: 'd.toFixed(2) + "s"', padding: 40)}
|
320
324
|
.call(g => g.selectAll(".tick:first-of-type text").remove())
|
321
325
|
JS
|
322
326
|
end
|
@@ -373,15 +377,15 @@ module Spoom
|
|
373
377
|
def plot
|
374
378
|
<<~JS
|
375
379
|
#{x_scale}
|
376
|
-
#{y_scale(min:
|
377
|
-
#{line(y:
|
380
|
+
#{y_scale(min: "0", max: "100", ticks: "tickValues([0, 25, 50, 75, 100])")}
|
381
|
+
#{line(y: "d.data.timestamp")}
|
378
382
|
#{x_ticks}
|
379
|
-
#{y_ticks(ticks:
|
383
|
+
#{y_ticks(ticks: "tickValues([25, 50, 75])", format: "d + '%'", padding: 30)}
|
380
384
|
JS
|
381
385
|
end
|
382
386
|
|
383
387
|
sig { override.params(y: String, color: String, curve: String).returns(String) }
|
384
|
-
def line(y:, color:
|
388
|
+
def line(y:, color: "strictnessColor(d.key)", curve: "curveCatmullRom.alpha(1)")
|
385
389
|
<<~JS
|
386
390
|
var area_#{id} = d3.area()
|
387
391
|
.x((d) => xScale_#{id}(parseDate(#{y})))
|
@@ -446,7 +450,7 @@ module Spoom
|
|
446
450
|
|
447
451
|
sig { params(id: String, snapshots: T::Array[Snapshot]).void }
|
448
452
|
def initialize(id, snapshots)
|
449
|
-
keys = [
|
453
|
+
keys = ["false", "true"]
|
450
454
|
data = snapshots.map do |snapshot|
|
451
455
|
{
|
452
456
|
timestamp: snapshot.commit_timestamp,
|
@@ -473,7 +477,7 @@ module Spoom
|
|
473
477
|
|
474
478
|
sig { params(id: String, snapshots: T::Array[Snapshot]).void }
|
475
479
|
def initialize(id, snapshots)
|
476
|
-
keys = [
|
480
|
+
keys = ["false", "true"]
|
477
481
|
data = snapshots.map do |snapshot|
|
478
482
|
{
|
479
483
|
timestamp: snapshot.commit_timestamp,
|
@@ -500,7 +504,7 @@ module Spoom
|
|
500
504
|
|
501
505
|
sig { params(id: String, snapshots: T::Array[Snapshot]).void }
|
502
506
|
def initialize(id, snapshots)
|
503
|
-
keys = [
|
507
|
+
keys = ["rbis", "files"]
|
504
508
|
data = snapshots.map do |snapshot|
|
505
509
|
{
|
506
510
|
timestamp: snapshot.commit_timestamp,
|
@@ -567,7 +571,7 @@ module Spoom
|
|
567
571
|
end
|
568
572
|
|
569
573
|
sig { override.params(y: String, color: String, curve: String).returns(String) }
|
570
|
-
def line(y:, color:
|
574
|
+
def line(y:, color: "strictnessColor(d.key)", curve: "curveCatmullRom.alpha(1)")
|
571
575
|
<<~JS
|
572
576
|
var area_#{id} = d3.area()
|
573
577
|
.x((d) => xScale_#{id}(parseDate(#{y})))
|
@@ -610,10 +614,10 @@ module Spoom
|
|
610
614
|
def plot
|
611
615
|
<<~JS
|
612
616
|
#{x_scale}
|
613
|
-
#{y_scale(min:
|
614
|
-
#{line(y:
|
617
|
+
#{y_scale(min: "0", max: "d3.max(data_#{id}, (d) => d.total + 10)", ticks: "tickValues([0, 25, 50, 75, 100])")}
|
618
|
+
#{line(y: "d.data.timestamp", color: "d.key == 'rbis' ? '#8673ff' : '#007bff'")}
|
615
619
|
#{x_ticks}
|
616
|
-
#{y_ticks(ticks:
|
620
|
+
#{y_ticks(ticks: "tickValues([25, 50, 75])", format: "d", padding: 20)}
|
617
621
|
JS
|
618
622
|
end
|
619
623
|
end
|
data/lib/spoom/coverage/d3.rb
CHANGED
@@ -8,94 +8,96 @@ require_relative "d3/timeline"
|
|
8
8
|
module Spoom
|
9
9
|
module Coverage
|
10
10
|
module D3
|
11
|
-
extend T::Sig
|
12
|
-
|
13
11
|
COLOR_IGNORE = "#999"
|
14
12
|
COLOR_FALSE = "#db4437"
|
15
13
|
COLOR_TRUE = "#0f9d58"
|
16
14
|
COLOR_STRICT = "#0a7340"
|
17
15
|
COLOR_STRONG = "#064828"
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
<<~CSS
|
22
|
-
svg {
|
23
|
-
width: 100%;
|
24
|
-
height: 100%;
|
25
|
-
}
|
17
|
+
class << self
|
18
|
+
extend T::Sig
|
26
19
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
border-radius: 4px;
|
35
|
-
position: absolute;
|
36
|
-
top: 0;
|
37
|
-
left: 0;
|
38
|
-
opacity: 0;
|
39
|
-
}
|
20
|
+
sig { returns(String) }
|
21
|
+
def header_style
|
22
|
+
<<~CSS
|
23
|
+
svg {
|
24
|
+
width: 100%;
|
25
|
+
height: 100%;
|
26
|
+
}
|
40
27
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
28
|
+
.tooltip {
|
29
|
+
font: 12px Arial, sans-serif;
|
30
|
+
color: #fff;
|
31
|
+
text-align: center;
|
32
|
+
background: rgba(0, 0, 0, 0.6);
|
33
|
+
padding: 5px;
|
34
|
+
border: 0px;
|
35
|
+
border-radius: 4px;
|
36
|
+
position: absolute;
|
37
|
+
top: 0;
|
38
|
+
left: 0;
|
39
|
+
opacity: 0;
|
40
|
+
}
|
48
41
|
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
.label {
|
43
|
+
font: 14px Arial, sans-serif;
|
44
|
+
font-weight: bold;
|
45
|
+
fill: #fff;
|
46
|
+
text-anchor: middle;
|
47
|
+
pointer-events: none;
|
48
|
+
}
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
.label .small {
|
51
|
+
font-size: 10px;
|
52
|
+
}
|
53
|
+
|
54
|
+
#{Pie.header_style}
|
55
|
+
#{CircleMap.header_style}
|
56
|
+
#{Timeline.header_style}
|
57
|
+
CSS
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
sig { params(palette: ColorPalette).returns(String) }
|
61
|
+
def header_script(palette)
|
62
|
+
<<~JS
|
63
|
+
var parseDate = d3.timeParse("%s");
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
65
|
+
function strictnessColor(strictness) {
|
66
|
+
switch(strictness) {
|
67
|
+
case "ignore":
|
68
|
+
return "#{palette.ignore}";
|
69
|
+
case "false":
|
70
|
+
return "#{palette.false}";
|
71
|
+
case "true":
|
72
|
+
return "#{palette.true}";
|
73
|
+
case "strict":
|
74
|
+
return "#{palette.strict}";
|
75
|
+
case "strong":
|
76
|
+
return "#{palette.strong}";
|
77
|
+
}
|
78
|
+
return "#{palette.false}";
|
76
79
|
}
|
77
|
-
return "#{palette.false}";
|
78
|
-
}
|
79
80
|
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
function toPercent(value, sum) {
|
82
|
+
return value ? Math.round(value * 100 / sum) : 0;
|
83
|
+
}
|
83
84
|
|
84
|
-
|
85
|
-
.append("div")
|
85
|
+
var tooltip = d3.select("body")
|
86
86
|
.append("div")
|
87
|
-
.
|
87
|
+
.append("div")
|
88
|
+
.attr("class", "tooltip");
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
90
|
+
function moveTooltip(d) {
|
91
|
+
return tooltip
|
92
|
+
.style("left", (d3.event.pageX + 20) + "px")
|
93
|
+
.style("top", (d3.event.pageY) + "px")
|
94
|
+
}
|
94
95
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
#{Pie.header_script}
|
97
|
+
#{CircleMap.header_script}
|
98
|
+
#{Timeline.header_script}
|
99
|
+
JS
|
100
|
+
end
|
99
101
|
end
|
100
102
|
|
101
103
|
class ColorPalette < T::Struct
|
@@ -109,7 +109,7 @@ module Spoom
|
|
109
109
|
abstract!
|
110
110
|
|
111
111
|
sig { void }
|
112
|
-
def initialize; end
|
112
|
+
def initialize; end # rubocop:disable Lint/MissingSuper
|
113
113
|
|
114
114
|
sig { override.returns(String) }
|
115
115
|
def html
|
@@ -136,17 +136,17 @@ module Spoom
|
|
136
136
|
|
137
137
|
sig { returns(D3::Pie::Sigils) }
|
138
138
|
def pie_sigils
|
139
|
-
D3::Pie::Sigils.new(
|
139
|
+
D3::Pie::Sigils.new("pie_sigils", "Sigils", snapshot)
|
140
140
|
end
|
141
141
|
|
142
142
|
sig { returns(D3::Pie::Calls) }
|
143
143
|
def pie_calls
|
144
|
-
D3::Pie::Calls.new(
|
144
|
+
D3::Pie::Calls.new("pie_calls", "Calls", snapshot)
|
145
145
|
end
|
146
146
|
|
147
147
|
sig { returns(D3::Pie::Sigs) }
|
148
148
|
def pie_sigs
|
149
|
-
D3::Pie::Sigs.new(
|
149
|
+
D3::Pie::Sigs.new("pie_sigs", "Sigs", snapshot)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -226,7 +226,7 @@ module Spoom
|
|
226
226
|
extend T::Sig
|
227
227
|
|
228
228
|
sig { params(sorbet_intro_commit: T.nilable(String), sorbet_intro_date: T.nilable(Time)).void }
|
229
|
-
def initialize(sorbet_intro_commit: nil, sorbet_intro_date: nil)
|
229
|
+
def initialize(sorbet_intro_commit: nil, sorbet_intro_date: nil) # rubocop:disable Lint/MissingSuper
|
230
230
|
@sorbet_intro_commit = sorbet_intro_commit
|
231
231
|
@sorbet_intro_date = sorbet_intro_date
|
232
232
|
end
|
@@ -235,7 +235,7 @@ module Spoom
|
|
235
235
|
def erb
|
236
236
|
<<~ERB
|
237
237
|
<div class="text-center" style="margin-top: 30px">
|
238
|
-
Typchecked by Sorbet since <b>#{@sorbet_intro_date&.strftime(
|
238
|
+
Typchecked by Sorbet since <b>#{@sorbet_intro_date&.strftime("%F")}</b>
|
239
239
|
(commit <b>#{@sorbet_intro_commit}</b>).
|
240
240
|
</div>
|
241
241
|
ERB
|
@@ -32,44 +32,49 @@ module Spoom
|
|
32
32
|
printer.print_snapshot(self)
|
33
33
|
end
|
34
34
|
|
35
|
-
sig { params(
|
36
|
-
def
|
37
|
-
|
35
|
+
sig { params(arg: T.untyped).returns(String) }
|
36
|
+
def to_json(*arg)
|
37
|
+
serialize.to_json(*arg)
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
snapshot.duration = obj.fetch("duration", 0)
|
47
|
-
snapshot.commit_sha = obj.fetch("commit_sha", nil)
|
48
|
-
snapshot.commit_timestamp = obj.fetch("commit_timestamp", nil)
|
49
|
-
snapshot.files = obj.fetch("files", 0)
|
50
|
-
snapshot.rbi_files = obj.fetch("rbi_files", 0)
|
51
|
-
snapshot.modules = obj.fetch("modules", 0)
|
52
|
-
snapshot.classes = obj.fetch("classes", 0)
|
53
|
-
snapshot.singleton_classes = obj.fetch("singleton_classes", 0)
|
54
|
-
snapshot.methods_with_sig = obj.fetch("methods_with_sig", 0)
|
55
|
-
snapshot.methods_without_sig = obj.fetch("methods_without_sig", 0)
|
56
|
-
snapshot.calls_typed = obj.fetch("calls_typed", 0)
|
57
|
-
snapshot.calls_untyped = obj.fetch("calls_untyped", 0)
|
58
|
-
|
59
|
-
sigils = obj.fetch("sigils", {})
|
60
|
-
if sigils
|
61
|
-
Snapshot::STRICTNESSES.each do |strictness|
|
62
|
-
next unless sigils.key?(strictness)
|
63
|
-
snapshot.sigils[strictness] = sigils[strictness]
|
64
|
-
end
|
40
|
+
class << self
|
41
|
+
extend T::Sig
|
42
|
+
|
43
|
+
sig { params(json: String).returns(Snapshot) }
|
44
|
+
def from_json(json)
|
45
|
+
from_obj(JSON.parse(json))
|
65
46
|
end
|
66
47
|
|
67
|
-
|
68
|
-
|
48
|
+
sig { params(obj: T::Hash[String, T.untyped]).returns(Snapshot) }
|
49
|
+
def from_obj(obj)
|
50
|
+
snapshot = Snapshot.new
|
51
|
+
snapshot.timestamp = obj.fetch("timestamp", 0)
|
52
|
+
snapshot.version_static = obj.fetch("version_static", nil)
|
53
|
+
snapshot.version_runtime = obj.fetch("version_runtime", nil)
|
54
|
+
snapshot.duration = obj.fetch("duration", 0)
|
55
|
+
snapshot.commit_sha = obj.fetch("commit_sha", nil)
|
56
|
+
snapshot.commit_timestamp = obj.fetch("commit_timestamp", nil)
|
57
|
+
snapshot.files = obj.fetch("files", 0)
|
58
|
+
snapshot.rbi_files = obj.fetch("rbi_files", 0)
|
59
|
+
snapshot.modules = obj.fetch("modules", 0)
|
60
|
+
snapshot.classes = obj.fetch("classes", 0)
|
61
|
+
snapshot.singleton_classes = obj.fetch("singleton_classes", 0)
|
62
|
+
snapshot.methods_with_sig = obj.fetch("methods_with_sig", 0)
|
63
|
+
snapshot.methods_without_sig = obj.fetch("methods_without_sig", 0)
|
64
|
+
snapshot.calls_typed = obj.fetch("calls_typed", 0)
|
65
|
+
snapshot.calls_untyped = obj.fetch("calls_untyped", 0)
|
69
66
|
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
sigils = obj.fetch("sigils", {})
|
68
|
+
if sigils
|
69
|
+
Snapshot::STRICTNESSES.each do |strictness|
|
70
|
+
next unless sigils.key?(strictness)
|
71
|
+
|
72
|
+
snapshot.sigils[strictness] = sigils[strictness]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
snapshot
|
77
|
+
end
|
73
78
|
end
|
74
79
|
end
|
75
80
|
|
@@ -119,6 +124,7 @@ module Spoom
|
|
119
124
|
indent
|
120
125
|
hash.each do |key, value|
|
121
126
|
next unless value > 0
|
127
|
+
|
122
128
|
printl("#{key}: #{value}#{percent(value, total)}")
|
123
129
|
end
|
124
130
|
dedent
|
@@ -127,6 +133,7 @@ module Spoom
|
|
127
133
|
sig { params(value: T.nilable(Integer), total: T.nilable(Integer)).returns(String) }
|
128
134
|
def percent(value, total)
|
129
135
|
return "" if value.nil? || total.nil? || total == 0
|
136
|
+
|
130
137
|
" (#{(value.to_f * 100.0 / total.to_f).round}%)"
|
131
138
|
end
|
132
139
|
end
|