spoom 1.1.0 → 1.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8ab95447c622919ce44c084fd3a3e6cfeb6c239f466bf956ba408909c4765b8
4
- data.tar.gz: 52ec4172e6b9ac96ab64c813bcd92ac71912903d64e2af850864454820f20a09
3
+ metadata.gz: b209723354af5be10930893accb559ecbb62afc1469d2d8a12f7a7af44d67d6c
4
+ data.tar.gz: 4bd2e43681783fceb004e5595218127b5838b5e09c47800c6d4d0905566e42f0
5
5
  SHA512:
6
- metadata.gz: 19f29b380868435e4fb21d27004541a4a319a6c4eae1df5603a22f11698b0ef814bb4a6175a3932a9288ec92f7f8998e961735033992cbfa91d64a7f1ee1b438
7
- data.tar.gz: 2da177e08833e1310d280bbf228e6763fbd3085e7d10780925acca0d50293062186f4b64b971e2ab436bae6f8120bbdd6c26bf6b04e25c92906a9f2cefa68751
6
+ metadata.gz: 99e8cccc29317edb58b84ba3a5713dfbfcf44c97bea40d2b4f30c256460983da7698847ea6fd9fc5a8c58c1aa6cb716e626a4540ac3e60302822b2d17efb194c
7
+ data.tar.gz: 055571522e43f963a1ee79a1cbd138d10d8ca685a252e5bfc64fc696abbf1812ae796bef764ab2d95359d1236012fe6cc45cfc48074997273f30df02e018a8b1
data/README.md CHANGED
@@ -226,6 +226,12 @@ Bump files using a custom instance of Sorbet:
226
226
  $ spoom bump --from false --to true --sorbet /path/to/sorbet/bin
227
227
  ```
228
228
 
229
+ Count the number of type-checking errors if all files were bumped to true:
230
+
231
+ ```
232
+ $ spoom bump --count-errors --dry
233
+ ```
234
+
229
235
  #### Interact with Sorbet LSP mode
230
236
 
231
237
  **Experimental**
@@ -15,7 +15,7 @@ module Spoom
15
15
 
16
16
  desc "snapshot", "Run srb tc and display metrics"
17
17
  option :save, type: :string, lazy_default: DATA_DIR, desc: "Save snapshot data as json"
18
- option :rbi, type: :boolean, default: true, desc: "Exclude RBI files from metrics"
18
+ option :rbi, type: :boolean, default: true, desc: "Include RBI files in metrics"
19
19
  option :sorbet, type: :string, desc: "Path to custom Sorbet bin"
20
20
  def snapshot
21
21
  in_sorbet_project!
@@ -54,6 +54,9 @@ module Spoom
54
54
  snapshot.version_static = Spoom::Sorbet.version_from_gemfile_lock(gem: "sorbet-static", path: path)
55
55
  snapshot.version_runtime = Spoom::Sorbet.version_from_gemfile_lock(gem: "sorbet-runtime", path: path)
56
56
 
57
+ files = Spoom::Sorbet.srb_files(new_config, path: path)
58
+ snapshot.rbi_files = files.count { |file| file.end_with?(".rbi") }
59
+
57
60
  snapshot
58
61
  end
59
62
 
@@ -81,8 +84,15 @@ module Spoom
81
84
  def self.sigils_tree(path: ".")
82
85
  config = sorbet_config(path: path)
83
86
  files = Sorbet.srb_files(config, path: path)
84
- files.select! { |file| file =~ /\.rb$/ }
87
+
88
+ extensions = config.allowed_extensions
89
+ extensions = [".rb"] if extensions.empty?
90
+ extensions -= [".rbi"]
91
+
92
+ pattern = /\.(#{Regexp.union(extensions.map { |ext| ext[1..-1] })})$/
93
+ files.select! { |file| file =~ pattern }
85
94
  files.reject! { |file| file =~ %r{/test/} }
95
+
86
96
  FileTree.new(files, strip_prefix: path)
87
97
  end
88
98
  end
@@ -36,10 +36,28 @@ module Spoom
36
36
  pointer-events: none;
37
37
  }
38
38
 
39
+ .area {
40
+ fill-opacity: 0.5;
41
+ }
42
+
43
+ .line {
44
+ stroke-width: 2;
45
+ fill: transparent;
46
+ }
47
+
48
+ .dot {
49
+ r: 2;
50
+ fill: #888;
51
+ }
52
+
39
53
  .inverted .grid line {
40
54
  stroke: #777;
41
55
  }
42
56
 
57
+ .inverted .area {
58
+ fill-opacity: 0.9;
59
+ }
60
+
43
61
  .inverted .axis text {
44
62
  fill: #fff;
45
63
  }
@@ -47,6 +65,10 @@ module Spoom
47
65
  .inverted .axis line {
48
66
  stroke: #fff;
49
67
  }
68
+
69
+ .inverted .dot {
70
+ fill: #fff;
71
+ }
50
72
  CSS
51
73
  end
52
74
 
@@ -170,7 +192,6 @@ module Spoom
170
192
  .y1((d) => yScale_#{id}(#{y}))
171
193
  .curve(d3.#{curve}))
172
194
  .attr("fill", "#{color}")
173
- .attr("fill-opacity", 0.5)
174
195
  HTML
175
196
  end
176
197
 
@@ -185,8 +206,6 @@ module Spoom
185
206
  .y((d) => yScale_#{id}(#{y}))
186
207
  .curve(d3.#{curve}))
187
208
  .attr("stroke", "#{color}")
188
- .attr("stroke-width", 3)
189
- .attr("fill", "transparent")
190
209
  HTML
191
210
  end
192
211
 
@@ -198,10 +217,8 @@ module Spoom
198
217
  .enter()
199
218
  .append("circle")
200
219
  .attr("class", "dot")
201
- .attr("r", 3)
202
220
  .attr("cx", (d) => xScale_#{id}(parseDate(d.timestamp)))
203
221
  .attr("cy", (d, i) => yScale_#{id}(#{y}))
204
- .attr("fill", "#aaa")
205
222
  .on("mouseover", (d) => tooltip.style("opacity", 1))
206
223
  .on("mousemove", tooltip_#{id})
207
224
  .on("mouseleave", (d) => tooltip.style("opacity", 0));
@@ -381,18 +398,15 @@ module Spoom
381
398
  layer.append("path")
382
399
  .attr("class", "area")
383
400
  .attr("d", area_#{id})
384
- .attr("fill", (d) => strictnessColor(d.key))
385
- .attr("fill-opacity", 0.9)
401
+ .attr("fill", (d) => #{color})
386
402
 
387
403
  svg_#{id}.selectAll("circle")
388
404
  .data(points_#{id})
389
405
  .enter()
390
406
  .append("circle")
391
407
  .attr("class", "dot")
392
- .attr("r", 2)
393
408
  .attr("cx", (d) => xScale_#{id}(parseDate(#{y})))
394
409
  .attr("cy", (d, i) => yScale_#{id}(d[1]))
395
- .attr("fill", "#fff")
396
410
  .on("mouseover", (d) => tooltip.style("opacity", 1))
397
411
  .on("mousemove", tooltip_#{id})
398
412
  .on("mouseleave", (d) => tooltip.style("opacity", 0));
@@ -480,6 +494,129 @@ module Spoom
480
494
  JS
481
495
  end
482
496
  end
497
+
498
+ class RBIs < Stacked
499
+ extend T::Sig
500
+
501
+ sig { params(id: String, snapshots: T::Array[Snapshot]).void }
502
+ def initialize(id, snapshots)
503
+ keys = ['rbis', 'files']
504
+ data = snapshots.map do |snapshot|
505
+ {
506
+ timestamp: snapshot.commit_timestamp,
507
+ commit: snapshot.commit_sha,
508
+ total: snapshot.files,
509
+ values: { files: snapshot.files - snapshot.rbi_files, rbis: snapshot.rbi_files },
510
+ }
511
+ end
512
+ super(id, data, keys)
513
+ end
514
+
515
+ sig { override.returns(String) }
516
+ def tooltip
517
+ <<~JS
518
+ function tooltip_#{id}(d) {
519
+ moveTooltip(d)
520
+ .html("commit <b>" + d.data.commit + "</b><br>"
521
+ + d3.timeFormat("%y/%m/%d")(parseDate(d.data.timestamp)) + "<br><br>"
522
+ + "Files: <b>" + d.data.values.files + "</b><br>"
523
+ + "RBIs: <b>" + d.data.values.rbis + "</b><br><br>"
524
+ + "Total: <b>" + d.data.total + "</b>")
525
+ }
526
+ JS
527
+ end
528
+
529
+ sig { override.returns(String) }
530
+ def script
531
+ <<~JS
532
+ #{tooltip}
533
+
534
+ var data_#{id} = #{@data.to_json};
535
+ var keys_#{id} = #{T.unsafe(@keys).to_json};
536
+
537
+ var stack_#{id} = d3.stack()
538
+ .keys(keys_#{id})
539
+ .value((d, key) => d.values[key]);
540
+
541
+ var layers_#{id} = stack_#{id}(data_#{id});
542
+
543
+ var points_#{id} = []
544
+ layers_#{id}.forEach(function(d) {
545
+ d.forEach(function(p) {
546
+ p.key = d.key
547
+ points_#{id}.push(p);
548
+ });
549
+ })
550
+
551
+ function draw_#{id}() {
552
+ var width_#{id} = document.getElementById("#{id}").clientWidth;
553
+ var height_#{id} = 200;
554
+
555
+ d3.select("##{id}").selectAll("*").remove()
556
+
557
+ var svg_#{id} = d3.select("##{id}")
558
+ .attr("width", width_#{id})
559
+ .attr("height", height_#{id});
560
+
561
+ #{plot}
562
+ }
563
+
564
+ draw_#{id}();
565
+ window.addEventListener("resize", draw_#{id});
566
+ JS
567
+ end
568
+
569
+ sig { override.params(y: String, color: String, curve: String).returns(String) }
570
+ def line(y:, color: 'strictnessColor(d.key)', curve: 'curveCatmullRom.alpha(1)')
571
+ <<~JS
572
+ var area_#{id} = d3.area()
573
+ .x((d) => xScale_#{id}(parseDate(#{y})))
574
+ .y0((d) => yScale_#{id}(d[0]))
575
+ .y1((d) => yScale_#{id}(d[1]))
576
+ .curve(d3.#{curve});
577
+
578
+ var layer = svg_#{id}.selectAll(".layer")
579
+ .data(layers_#{id})
580
+ .enter().append("g")
581
+ .attr("class", "layer")
582
+
583
+ layer.append("path")
584
+ .attr("class", "area")
585
+ .attr("d", area_#{id})
586
+ .attr("fill", (d) => #{color})
587
+
588
+ layer.append("path")
589
+ .attr("class", "line")
590
+ .attr("d", d3.line()
591
+ .x((d) => xScale_#{id}(parseDate(#{y})))
592
+ .y((d, i) => yScale_#{id}(d[1]))
593
+ .curve(d3.#{curve}))
594
+ .attr("stroke", (d) => #{color})
595
+
596
+ svg_#{id}.selectAll("circle")
597
+ .data(points_#{id})
598
+ .enter()
599
+ .append("circle")
600
+ .attr("class", "dot")
601
+ .attr("cx", (d) => xScale_#{id}(parseDate(#{y})))
602
+ .attr("cy", (d, i) => yScale_#{id}(d[1]))
603
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
604
+ .on("mousemove", tooltip_#{id})
605
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
606
+ JS
607
+ end
608
+
609
+ sig { override.returns(String) }
610
+ def plot
611
+ <<~JS
612
+ #{x_scale}
613
+ #{y_scale(min: '0', max: "d3.max(data_#{id}, (d) => d.total + 10)", ticks: 'tickValues([0, 25, 50, 75, 100])')}
614
+ #{line(y: 'd.data.timestamp', color: "d.key == 'rbis' ? '#8673ff' : '#007bff'")}
615
+ #{x_ticks}
616
+ #{y_ticks(ticks: 'tickValues([25, 50, 75])', format: 'd', padding: 20)}
617
+ JS
618
+ end
619
+ end
483
620
  end
484
621
  end
485
622
  end
@@ -194,6 +194,15 @@ module Spoom
194
194
  end
195
195
  end
196
196
 
197
+ class RBIs < Timeline
198
+ extend T::Sig
199
+
200
+ sig { params(snapshots: T::Array[Coverage::Snapshot], title: String).void }
201
+ def initialize(snapshots:, title: "RBIs Timeline")
202
+ super(title: title, timeline: D3::Timeline::RBIs.new("timeline_rbis", snapshots))
203
+ end
204
+ end
205
+
197
206
  class Versions < Timeline
198
207
  extend T::Sig
199
208
 
@@ -298,6 +307,7 @@ module Spoom
298
307
  cards << Cards::Timeline::Sigils.new(snapshots: snapshots)
299
308
  cards << Cards::Timeline::Calls.new(snapshots: snapshots)
300
309
  cards << Cards::Timeline::Sigs.new(snapshots: snapshots)
310
+ cards << Cards::Timeline::RBIs.new(snapshots: snapshots)
301
311
  cards << Cards::Timeline::Versions.new(snapshots: snapshots)
302
312
  cards << Cards::Timeline::Runtimes.new(snapshots: snapshots)
303
313
  cards << Cards::SorbetIntro.new(sorbet_intro_commit: sorbet_intro_commit, sorbet_intro_date: sorbet_intro_date)
@@ -13,6 +13,7 @@ module Spoom
13
13
  prop :commit_sha, T.nilable(String), default: nil
14
14
  prop :commit_timestamp, T.nilable(Integer), default: nil
15
15
  prop :files, Integer, default: 0
16
+ prop :rbi_files, Integer, default: 0
16
17
  prop :modules, Integer, default: 0
17
18
  prop :classes, Integer, default: 0
18
19
  prop :singleton_classes, Integer, default: 0
@@ -46,6 +47,7 @@ module Spoom
46
47
  snapshot.commit_sha = obj.fetch("commit_sha", nil)
47
48
  snapshot.commit_timestamp = obj.fetch("commit_timestamp", nil)
48
49
  snapshot.files = obj.fetch("files", 0)
50
+ snapshot.rbi_files = obj.fetch("rbi_files", 0)
49
51
  snapshot.modules = obj.fetch("modules", 0)
50
52
  snapshot.classes = obj.fetch("classes", 0)
51
53
  snapshot.singleton_classes = obj.fetch("singleton_classes", 0)
@@ -86,7 +88,7 @@ module Spoom
86
88
  end
87
89
  printl("Content:")
88
90
  indent
89
- printl("files: #{snapshot.files}")
91
+ printl("files: #{snapshot.files} (including #{snapshot.rbi_files} RBIs)")
90
92
  printl("modules: #{snapshot.modules}")
91
93
  printl("classes: #{snapshot.classes - snapshot.singleton_classes}")
92
94
  printl("methods: #{methods}")
data/lib/spoom/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Spoom
5
- VERSION = "1.1.0"
5
+ VERSION = "1.1.1"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spoom
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Terrasa
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-19 00:00:00.000000000 Z
11
+ date: 2021-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler