spoom 1.0.6 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/README.md +51 -2
- data/lib/spoom.rb +20 -2
- data/lib/spoom/cli.rb +25 -14
- data/lib/spoom/cli/bump.rb +106 -13
- data/lib/spoom/cli/config.rb +3 -3
- data/lib/spoom/cli/coverage.rb +57 -42
- data/lib/spoom/cli/helper.rb +88 -9
- data/lib/spoom/cli/lsp.rb +20 -20
- data/lib/spoom/cli/run.rb +55 -25
- data/lib/spoom/coverage.rb +33 -7
- data/lib/spoom/coverage/d3/timeline.rb +146 -9
- data/lib/spoom/coverage/report.rb +13 -3
- data/lib/spoom/coverage/snapshot.rb +3 -1
- data/lib/spoom/file_tree.rb +1 -1
- data/lib/spoom/git.rb +2 -1
- data/lib/spoom/printer.rb +0 -1
- data/lib/spoom/sorbet.rb +97 -58
- data/lib/spoom/sorbet/config.rb +30 -0
- data/lib/spoom/sorbet/errors.rb +8 -0
- data/lib/spoom/sorbet/lsp.rb +2 -6
- data/lib/spoom/sorbet/sigils.rb +3 -3
- data/lib/spoom/test_helpers/project.rb +9 -0
- data/lib/spoom/version.rb +2 -2
- metadata +6 -7
- data/lib/spoom/config.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b209723354af5be10930893accb559ecbb62afc1469d2d8a12f7a7af44d67d6c
|
4
|
+
data.tar.gz: 4bd2e43681783fceb004e5595218127b5838b5e09c47800c6d4d0905566e42f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99e8cccc29317edb58b84ba3a5713dfbfcf44c97bea40d2b4f30c256460983da7698847ea6fd9fc5a8c58c1aa6cb716e626a4540ac3e60302822b2d17efb194c
|
7
|
+
data.tar.gz: 055571522e43f963a1ee79a1cbd138d10d8ca685a252e5bfc64fc696abbf1812ae796bef764ab2d95359d1236012fe6cc45cfc48074997273f30df02e018a8b1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -69,7 +69,7 @@ $ spoom files
|
|
69
69
|
List all typechecking errors sorted by location:
|
70
70
|
|
71
71
|
```
|
72
|
-
$ spoom tc -s
|
72
|
+
$ spoom tc -s loc
|
73
73
|
```
|
74
74
|
|
75
75
|
List all typechecking errors sorted by error code first:
|
@@ -96,6 +96,31 @@ These options can be combined:
|
|
96
96
|
$ spoom tc -s -c 7004 -l 10
|
97
97
|
```
|
98
98
|
|
99
|
+
Remove duplicated error lines:
|
100
|
+
|
101
|
+
```
|
102
|
+
$ spoom tc -u
|
103
|
+
```
|
104
|
+
|
105
|
+
Format each error line:
|
106
|
+
|
107
|
+
```
|
108
|
+
$ spoom tc -f '%C - %F:%L: %M'
|
109
|
+
```
|
110
|
+
|
111
|
+
Where:
|
112
|
+
|
113
|
+
* `%C` is the error code
|
114
|
+
* `%F` is the file the error is from
|
115
|
+
* `%L` is the line the error is from
|
116
|
+
* `%M` is the error message
|
117
|
+
|
118
|
+
Hide the `Errors: X` at the end of the list:
|
119
|
+
|
120
|
+
```
|
121
|
+
$ spoom tc --no-count
|
122
|
+
```
|
123
|
+
|
99
124
|
#### Typing coverage
|
100
125
|
|
101
126
|
Show metrics about the project contents and the typing coverage:
|
@@ -183,6 +208,30 @@ Bump the strictness from all files currently at `typed: false` to `typed: true`
|
|
183
208
|
$ spoom bump --from false --to true -f
|
184
209
|
```
|
185
210
|
|
211
|
+
Bump the strictness from a list of files (one file by line):
|
212
|
+
|
213
|
+
```
|
214
|
+
$ spoom bump --from false --to true -o list.txt
|
215
|
+
```
|
216
|
+
|
217
|
+
Check if files can be bumped without applying any change:
|
218
|
+
|
219
|
+
```
|
220
|
+
$ spoom bump --from false --to true --dry
|
221
|
+
```
|
222
|
+
|
223
|
+
Bump files using a custom instance of Sorbet:
|
224
|
+
|
225
|
+
```
|
226
|
+
$ spoom bump --from false --to true --sorbet /path/to/sorbet/bin
|
227
|
+
```
|
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
|
+
|
186
235
|
#### Interact with Sorbet LSP mode
|
187
236
|
|
188
237
|
**Experimental**
|
@@ -273,7 +322,7 @@ Create an LSP client:
|
|
273
322
|
|
274
323
|
```rb
|
275
324
|
client = Spoom::LSP::Client.new(
|
276
|
-
Spoom::
|
325
|
+
Spoom::Sorbet::BIN_PATH,
|
277
326
|
"--lsp",
|
278
327
|
"--enable-all-experimental-lsp-features",
|
279
328
|
"--disable-watchman",
|
data/lib/spoom.rb
CHANGED
@@ -1,13 +1,31 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "colorize"
|
4
5
|
require "sorbet-runtime"
|
5
6
|
|
6
7
|
module Spoom
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
SPOOM_PATH = (Pathname.new(__FILE__) / ".." / "..").to_s
|
11
|
+
|
7
12
|
class Error < StandardError; end
|
8
|
-
end
|
9
13
|
|
10
|
-
|
14
|
+
sig do
|
15
|
+
params(
|
16
|
+
cmd: String,
|
17
|
+
arg: String,
|
18
|
+
path: String,
|
19
|
+
capture_err: T::Boolean
|
20
|
+
).returns([String, T::Boolean])
|
21
|
+
end
|
22
|
+
def self.exec(cmd, *arg, path: '.', capture_err: false)
|
23
|
+
method = capture_err ? "popen2e" : "popen2"
|
24
|
+
Open3.send(method, [cmd, *arg].join(" "), chdir: path) do |_, o, t|
|
25
|
+
[o.read, T.cast(t.value, Process::Status).success?]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
11
29
|
|
12
30
|
require "spoom/sorbet"
|
13
31
|
require "spoom/cli"
|
data/lib/spoom/cli.rb
CHANGED
@@ -17,43 +17,54 @@ module Spoom
|
|
17
17
|
extend T::Sig
|
18
18
|
include Helper
|
19
19
|
|
20
|
-
class_option :color,
|
21
|
-
class_option :path,
|
20
|
+
class_option :color, type: :boolean, default: true, desc: "Use colors"
|
21
|
+
class_option :path, type: :string, default: ".", aliases: :p, desc: "Run spoom in a specific path"
|
22
|
+
|
22
23
|
map T.unsafe(%w[--version -v] => :__print_version)
|
23
24
|
|
24
|
-
desc "bump", "
|
25
|
+
desc "bump", "Bump Sorbet sigils from `false` to `true` when no errors"
|
25
26
|
subcommand "bump", Spoom::Cli::Bump
|
26
27
|
|
27
|
-
desc "config", "
|
28
|
+
desc "config", "Manage Sorbet config"
|
28
29
|
subcommand "config", Spoom::Cli::Config
|
29
30
|
|
30
|
-
desc "coverage", "
|
31
|
+
desc "coverage", "Collect metrics related to Sorbet coverage"
|
31
32
|
subcommand "coverage", Spoom::Cli::Coverage
|
32
33
|
|
33
|
-
desc "lsp", "
|
34
|
+
desc "lsp", "Send LSP requests to Sorbet"
|
34
35
|
subcommand "lsp", Spoom::Cli::LSP
|
35
36
|
|
36
|
-
desc "tc", "
|
37
|
+
desc "tc", "Run Sorbet and parses its output"
|
37
38
|
subcommand "tc", Spoom::Cli::Run
|
38
39
|
|
39
|
-
desc "files", "
|
40
|
+
desc "files", "List all the files typechecked by Sorbet"
|
41
|
+
option :tree, type: :boolean, default: true, desc: "Display list as an indented tree"
|
42
|
+
option :rbi, type: :boolean, default: true, desc: "Show RBI files"
|
40
43
|
def files
|
41
44
|
in_sorbet_project!
|
42
45
|
|
43
46
|
path = exec_path
|
44
|
-
config =
|
47
|
+
config = sorbet_config
|
45
48
|
files = Spoom::Sorbet.srb_files(config, path: path)
|
46
49
|
|
47
|
-
|
50
|
+
unless options[:rbi]
|
51
|
+
files = files.reject { |file| file.end_with?(".rbi") }
|
52
|
+
end
|
53
|
+
|
48
54
|
if files.empty?
|
49
|
-
|
50
|
-
|
55
|
+
say_error("No file matching `#{sorbet_config_file}`")
|
56
|
+
exit(1)
|
57
|
+
end
|
58
|
+
|
59
|
+
if options[:tree]
|
51
60
|
tree = FileTree.new(files, strip_prefix: path)
|
52
|
-
tree.print(colors: options[:color], indent_level:
|
61
|
+
tree.print(colors: options[:color], indent_level: 0)
|
62
|
+
else
|
63
|
+
puts files
|
53
64
|
end
|
54
65
|
end
|
55
66
|
|
56
|
-
desc "--version", "
|
67
|
+
desc "--version", "Show version"
|
57
68
|
def __print_version
|
58
69
|
puts "Spoom v#{Spoom::VERSION}"
|
59
70
|
end
|
data/lib/spoom/cli/bump.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'find'
|
@@ -12,47 +12,140 @@ module Spoom
|
|
12
12
|
|
13
13
|
default_task :bump
|
14
14
|
|
15
|
-
desc "bump DIRECTORY", "
|
16
|
-
option :from, type: :string, default: Spoom::Sorbet::Sigils::STRICTNESS_FALSE
|
17
|
-
|
18
|
-
option :
|
15
|
+
desc "bump DIRECTORY", "Change Sorbet sigils from one strictness to another when no errors"
|
16
|
+
option :from, type: :string, default: Spoom::Sorbet::Sigils::STRICTNESS_FALSE,
|
17
|
+
desc: "Change only files from this strictness"
|
18
|
+
option :to, type: :string, default: Spoom::Sorbet::Sigils::STRICTNESS_TRUE,
|
19
|
+
desc: "Change files to this strictness"
|
20
|
+
option :force, type: :boolean, default: false, aliases: :f,
|
21
|
+
desc: "Change strictness without type checking"
|
22
|
+
option :sorbet, type: :string, desc: "Path to custom Sorbet bin"
|
23
|
+
option :dry, type: :boolean, default: false, aliases: :d,
|
24
|
+
desc: "Only display what would happen, do not actually change sigils"
|
25
|
+
option :only, type: :string, default: nil, aliases: :o,
|
26
|
+
desc: "Only change specified list (one file by line)"
|
27
|
+
option :suggest_bump_command, type: :string,
|
28
|
+
desc: "Command to suggest if files can be bumped"
|
29
|
+
option :count_errors, type: :boolean, default: false,
|
30
|
+
desc: "Count the number of errors if all files were bumped"
|
19
31
|
sig { params(directory: String).void }
|
20
32
|
def bump(directory = ".")
|
33
|
+
in_sorbet_project!
|
34
|
+
|
21
35
|
from = options[:from]
|
22
36
|
to = options[:to]
|
23
37
|
force = options[:force]
|
38
|
+
dry = options[:dry]
|
39
|
+
only = options[:only]
|
40
|
+
cmd = options[:suggest_bump_command]
|
41
|
+
exec_path = File.expand_path(self.exec_path)
|
24
42
|
|
25
43
|
unless Sorbet::Sigils.valid_strictness?(from)
|
26
|
-
say_error("Invalid strictness
|
44
|
+
say_error("Invalid strictness `#{from}` for option `--from`")
|
27
45
|
exit(1)
|
28
46
|
end
|
29
47
|
|
30
48
|
unless Sorbet::Sigils.valid_strictness?(to)
|
31
|
-
say_error("Invalid strictness
|
49
|
+
say_error("Invalid strictness `#{to}` for option `--to`")
|
32
50
|
exit(1)
|
33
51
|
end
|
34
52
|
|
53
|
+
if options[:count_errors] && !dry
|
54
|
+
say_error("`--count-errors` can only be used with `--dry`")
|
55
|
+
exit(1)
|
56
|
+
end
|
57
|
+
|
58
|
+
say("Checking files...")
|
59
|
+
|
60
|
+
directory = File.expand_path(directory)
|
35
61
|
files_to_bump = Sorbet::Sigils.files_with_sigil_strictness(directory, from)
|
36
62
|
|
63
|
+
files_from_config = config_files(path: exec_path)
|
64
|
+
files_to_bump.select! { |file| files_from_config.include?(file) }
|
65
|
+
|
66
|
+
if only
|
67
|
+
list = File.read(only).lines.map { |file| File.expand_path(file.strip) }
|
68
|
+
files_to_bump.select! { |file| list.include?(File.expand_path(file)) }
|
69
|
+
end
|
70
|
+
|
71
|
+
say("\n")
|
72
|
+
|
73
|
+
if files_to_bump.empty?
|
74
|
+
say("No file to bump from `#{from}` to `#{to}`")
|
75
|
+
exit(0)
|
76
|
+
end
|
77
|
+
|
37
78
|
Sorbet::Sigils.change_sigil_in_files(files_to_bump, to)
|
38
79
|
|
39
|
-
|
80
|
+
if force
|
81
|
+
print_changes(files_to_bump, command: cmd, from: from, to: to, dry: dry, path: exec_path)
|
82
|
+
undo_changes(files_to_bump, from) if dry
|
83
|
+
exit(files_to_bump.empty?)
|
84
|
+
end
|
40
85
|
|
41
|
-
output, no_errors = Sorbet.srb_tc(
|
86
|
+
output, no_errors = Sorbet.srb_tc(
|
87
|
+
"--no-error-sections",
|
88
|
+
path: exec_path,
|
89
|
+
capture_err: true,
|
90
|
+
sorbet_bin: options[:sorbet]
|
91
|
+
)
|
42
92
|
|
43
|
-
|
93
|
+
if no_errors
|
94
|
+
print_changes(files_to_bump, command: cmd, from: from, to: to, dry: dry, path: exec_path)
|
95
|
+
undo_changes(files_to_bump, from) if dry
|
96
|
+
exit(files_to_bump.empty?)
|
97
|
+
end
|
44
98
|
|
45
99
|
errors = Sorbet::Errors::Parser.parse_string(output)
|
46
100
|
|
47
101
|
files_with_errors = errors.map do |err|
|
48
|
-
path = err.file
|
49
|
-
|
102
|
+
path = File.expand_path(err.file)
|
103
|
+
next unless path.start_with?(directory)
|
104
|
+
next unless File.file?(path)
|
105
|
+
path
|
50
106
|
end.compact.uniq
|
51
107
|
|
52
|
-
|
108
|
+
undo_changes(files_with_errors, from)
|
109
|
+
|
110
|
+
say("Found #{errors.length} type checking error#{'s' if errors.length > 1}") if options[:count_errors]
|
111
|
+
|
112
|
+
files_changed = files_to_bump - files_with_errors
|
113
|
+
print_changes(files_changed, command: cmd, from: from, to: to, dry: dry, path: exec_path)
|
114
|
+
undo_changes(files_to_bump, from) if dry
|
115
|
+
exit(files_changed.empty?)
|
53
116
|
end
|
54
117
|
|
55
118
|
no_commands do
|
119
|
+
def print_changes(files, command:, from: "false", to: "true", dry: false, path: File.expand_path("."))
|
120
|
+
if files.empty?
|
121
|
+
say("No file to bump from `#{from}` to `#{to}`")
|
122
|
+
return
|
123
|
+
end
|
124
|
+
message = StringIO.new
|
125
|
+
message << (dry ? "Can bump" : "Bumped")
|
126
|
+
message << " `#{files.size}` file#{'s' if files.size > 1}"
|
127
|
+
message << " from `#{from}` to `#{to}`:"
|
128
|
+
say(message.string)
|
129
|
+
files.each do |file|
|
130
|
+
file_path = Pathname.new(file).relative_path_from(path)
|
131
|
+
say(" + #{file_path}")
|
132
|
+
end
|
133
|
+
if dry && command
|
134
|
+
say("\nRun `#{command}` to bump them")
|
135
|
+
elsif dry
|
136
|
+
say("\nRun `spoom bump --from #{from} --to #{to}` to bump them")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def undo_changes(files, from_strictness)
|
141
|
+
Sorbet::Sigils.change_sigil_in_files(files, from_strictness)
|
142
|
+
end
|
143
|
+
|
144
|
+
def config_files(path: ".")
|
145
|
+
config = sorbet_config
|
146
|
+
files = Sorbet.srb_files(config, path: path)
|
147
|
+
files.map { |file| File.expand_path(file) }
|
148
|
+
end
|
56
149
|
end
|
57
150
|
end
|
58
151
|
end
|
data/lib/spoom/cli/config.rb
CHANGED
@@ -11,12 +11,12 @@ module Spoom
|
|
11
11
|
|
12
12
|
default_task :show
|
13
13
|
|
14
|
-
desc "show", "
|
14
|
+
desc "show", "Show Sorbet config"
|
15
15
|
def show
|
16
16
|
in_sorbet_project!
|
17
|
-
config =
|
17
|
+
config = sorbet_config
|
18
18
|
|
19
|
-
say("Found Sorbet config at `#{
|
19
|
+
say("Found Sorbet config at `#{sorbet_config_file}`.")
|
20
20
|
|
21
21
|
say("\nPaths typechecked:")
|
22
22
|
if config.paths.empty?
|
data/lib/spoom/cli/coverage.rb
CHANGED
@@ -13,13 +13,16 @@ module Spoom
|
|
13
13
|
|
14
14
|
default_task :snapshot
|
15
15
|
|
16
|
-
desc "snapshot", "
|
17
|
-
option :save, type: :string, desc: "Save snapshot data as json"
|
16
|
+
desc "snapshot", "Run srb tc and display metrics"
|
17
|
+
option :save, type: :string, lazy_default: DATA_DIR, desc: "Save snapshot data as json"
|
18
|
+
option :rbi, type: :boolean, default: true, desc: "Include RBI files in metrics"
|
19
|
+
option :sorbet, type: :string, desc: "Path to custom Sorbet bin"
|
18
20
|
def snapshot
|
19
21
|
in_sorbet_project!
|
20
|
-
|
21
22
|
path = exec_path
|
22
|
-
|
23
|
+
sorbet = options[:sorbet]
|
24
|
+
|
25
|
+
snapshot = Spoom::Coverage.snapshot(path: path, rbi: options[:rbi], sorbet_bin: sorbet)
|
23
26
|
snapshot.print
|
24
27
|
|
25
28
|
save_dir = options[:save]
|
@@ -27,29 +30,35 @@ module Spoom
|
|
27
30
|
FileUtils.mkdir_p(save_dir)
|
28
31
|
file = "#{save_dir}/#{snapshot.commit_sha || snapshot.timestamp}.json"
|
29
32
|
File.write(file, snapshot.to_json)
|
30
|
-
|
33
|
+
say("\nSnapshot data saved under `#{file}`")
|
31
34
|
end
|
32
35
|
|
33
|
-
desc "timeline", "
|
34
|
-
option :from, type: :string
|
35
|
-
option :to, type: :string, default: Time.now.strftime("%F")
|
36
|
-
option :save, type: :string, desc: "Save snapshot data as json"
|
36
|
+
desc "timeline", "Replay a project and collect metrics"
|
37
|
+
option :from, type: :string, desc: "From commit date"
|
38
|
+
option :to, type: :string, default: Time.now.strftime("%F"), desc: "To commit date"
|
39
|
+
option :save, type: :string, lazy_default: DATA_DIR, desc: "Save snapshot data as json"
|
37
40
|
option :bundle_install, type: :boolean, desc: "Execute `bundle install` before collecting metrics"
|
41
|
+
option :sorbet, type: :string, desc: "Path to custom Sorbet bin"
|
38
42
|
def timeline
|
39
43
|
in_sorbet_project!
|
40
44
|
path = exec_path
|
45
|
+
sorbet = options[:sorbet]
|
41
46
|
|
42
47
|
sha_before = Spoom::Git.last_commit(path: path)
|
43
48
|
unless sha_before
|
44
49
|
say_error("Not in a git repository")
|
45
|
-
|
50
|
+
say_error("\nSpoom needs to checkout into your previous commits to build the timeline.", status: nil)
|
46
51
|
exit(1)
|
47
52
|
end
|
48
53
|
|
49
54
|
unless Spoom::Git.workdir_clean?(path: path)
|
50
55
|
say_error("Uncommited changes")
|
51
|
-
|
52
|
-
|
56
|
+
say_error(<<~ERR, status: nil)
|
57
|
+
|
58
|
+
Spoom needs to checkout into your previous commits to build the timeline."
|
59
|
+
|
60
|
+
Please `git commit` or `git stash` your changes then try again
|
61
|
+
ERR
|
53
62
|
exit(1)
|
54
63
|
end
|
55
64
|
|
@@ -69,13 +78,13 @@ module Spoom
|
|
69
78
|
ticks = timeline.ticks
|
70
79
|
|
71
80
|
if ticks.empty?
|
72
|
-
say_error("No commits to replay, try different
|
81
|
+
say_error("No commits to replay, try different `--from` and `--to` options")
|
73
82
|
exit(1)
|
74
83
|
end
|
75
84
|
|
76
85
|
ticks.each_with_index do |sha, i|
|
77
86
|
date = Spoom::Git.commit_time(sha, path: path)
|
78
|
-
|
87
|
+
say("Analyzing commit `#{sha}` - #{date&.strftime('%F')} (#{i + 1} / #{ticks.size})")
|
79
88
|
|
80
89
|
Spoom::Git.checkout(sha, path: path)
|
81
90
|
|
@@ -83,32 +92,38 @@ module Spoom
|
|
83
92
|
if options[:bundle_install]
|
84
93
|
Bundler.with_clean_env do
|
85
94
|
next unless bundle_install(path, sha)
|
86
|
-
snapshot = Spoom::Coverage.snapshot(path: path)
|
95
|
+
snapshot = Spoom::Coverage.snapshot(path: path, sorbet_bin: sorbet)
|
87
96
|
end
|
88
97
|
else
|
89
|
-
snapshot = Spoom::Coverage.snapshot(path: path)
|
98
|
+
snapshot = Spoom::Coverage.snapshot(path: path, sorbet_bin: sorbet)
|
90
99
|
end
|
91
100
|
next unless snapshot
|
92
101
|
|
93
102
|
snapshot.print(indent_level: 2)
|
94
|
-
|
103
|
+
say("\n")
|
95
104
|
|
96
105
|
next unless save_dir
|
97
106
|
file = "#{save_dir}/#{sha}.json"
|
98
107
|
File.write(file, snapshot.to_json)
|
99
|
-
|
108
|
+
say(" Snapshot data saved under `#{file}`\n\n")
|
100
109
|
end
|
101
110
|
Spoom::Git.checkout(sha_before, path: path)
|
102
111
|
end
|
103
112
|
|
104
|
-
desc "report", "
|
105
|
-
option :data, type: :string, desc: "Snapshots JSON data"
|
106
|
-
option :file, type: :string, default: "spoom_report.html", aliases: :f
|
107
|
-
|
108
|
-
option :
|
109
|
-
|
110
|
-
option :
|
111
|
-
|
113
|
+
desc "report", "Produce a typing coverage report"
|
114
|
+
option :data, type: :string, default: DATA_DIR, desc: "Snapshots JSON data"
|
115
|
+
option :file, type: :string, default: "spoom_report.html", aliases: :f,
|
116
|
+
desc: "Save report to file"
|
117
|
+
option :color_ignore, type: :string, default: Spoom::Coverage::D3::COLOR_IGNORE,
|
118
|
+
desc: "Color used for typed: ignore"
|
119
|
+
option :color_false, type: :string, default: Spoom::Coverage::D3::COLOR_FALSE,
|
120
|
+
desc: "Color used for typed: false"
|
121
|
+
option :color_true, type: :string, default: Spoom::Coverage::D3::COLOR_TRUE,
|
122
|
+
desc: "Color used for typed: true"
|
123
|
+
option :color_strict, type: :string, default: Spoom::Coverage::D3::COLOR_STRICT,
|
124
|
+
desc: "Color used for typed: strict"
|
125
|
+
option :color_strong, type: :string, default: Spoom::Coverage::D3::COLOR_STRONG,
|
126
|
+
desc: "Color used for typed: strong"
|
112
127
|
def report
|
113
128
|
in_sorbet_project!
|
114
129
|
|
@@ -135,20 +150,20 @@ module Spoom
|
|
135
150
|
report = Spoom::Coverage.report(snapshots, palette: palette, path: exec_path)
|
136
151
|
file = options[:file]
|
137
152
|
File.write(file, report.html)
|
138
|
-
|
139
|
-
|
153
|
+
say("Report generated under `#{file}`")
|
154
|
+
say("\nUse `spoom coverage open` to open it.")
|
140
155
|
end
|
141
156
|
|
142
|
-
desc "open", "
|
157
|
+
desc "open", "Open the typing coverage report"
|
143
158
|
def open(file = "spoom_report.html")
|
144
159
|
unless File.exist?(file)
|
145
|
-
say_error("No report file to open
|
146
|
-
|
160
|
+
say_error("No report file to open `#{file}`")
|
161
|
+
say_error(<<~ERR, status: nil)
|
147
162
|
|
148
|
-
If you already generated a report under another name use #{
|
163
|
+
If you already generated a report under another name use #{blue('spoom coverage open PATH')}.
|
149
164
|
|
150
|
-
To generate a report run #{
|
151
|
-
|
165
|
+
To generate a report run #{blue('spoom coverage report')}.
|
166
|
+
ERR
|
152
167
|
exit(1)
|
153
168
|
end
|
154
169
|
|
@@ -160,7 +175,7 @@ module Spoom
|
|
160
175
|
return nil unless string
|
161
176
|
Time.parse(string)
|
162
177
|
rescue ArgumentError
|
163
|
-
say_error("Invalid date `#{string}` for option
|
178
|
+
say_error("Invalid date `#{string}` for option `#{option}` (expected format `YYYY-MM-DD`)")
|
164
179
|
exit(1)
|
165
180
|
end
|
166
181
|
|
@@ -169,21 +184,21 @@ module Spoom
|
|
169
184
|
opts[:chdir] = path
|
170
185
|
out, status = Open3.capture2e("bundle install", opts)
|
171
186
|
unless status.success?
|
172
|
-
say_error("Can't run `bundle install` for commit
|
173
|
-
|
187
|
+
say_error("Can't run `bundle install` for commit `#{sha}`. Skipping snapshot")
|
188
|
+
say_error(out, status: nil)
|
174
189
|
return false
|
175
190
|
end
|
176
191
|
true
|
177
192
|
end
|
178
193
|
|
179
194
|
def message_no_data(file)
|
180
|
-
say_error("No snapshot files found in
|
181
|
-
|
195
|
+
say_error("No snapshot files found in `#{file}`")
|
196
|
+
say_error(<<~ERR, status: nil)
|
182
197
|
|
183
|
-
If you already generated snapshot files under another directory use #{
|
198
|
+
If you already generated snapshot files under another directory use #{blue('spoom coverage report PATH')}.
|
184
199
|
|
185
|
-
To generate snapshot files run #{
|
186
|
-
|
200
|
+
To generate snapshot files run #{blue('spoom coverage timeline --save-dir spoom_data')}.
|
201
|
+
ERR
|
187
202
|
end
|
188
203
|
end
|
189
204
|
end
|