spoom 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
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