spoom 1.0.5 → 1.1.0
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 +0 -1
- data/README.md +45 -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 +22 -6
- data/lib/spoom/coverage/report.rb +3 -3
- 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
- data/templates/card.erb +8 -0
- data/templates/card_snapshot.erb +22 -0
- data/templates/page.erb +50 -0
- metadata +9 -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: c8ab95447c622919ce44c084fd3a3e6cfeb6c239f466bf956ba408909c4765b8
|
4
|
+
data.tar.gz: 52ec4172e6b9ac96ab64c813bcd92ac71912903d64e2af850864454820f20a09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19f29b380868435e4fb21d27004541a4a319a6c4eae1df5603a22f11698b0ef814bb4a6175a3932a9288ec92f7f8998e961735033992cbfa91d64a7f1ee1b438
|
7
|
+
data.tar.gz: 2da177e08833e1310d280bbf228e6763fbd3085e7d10780925acca0d50293062186f4b64b971e2ab436bae6f8120bbdd6c26bf6b04e25c92906a9f2cefa68751
|
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,24 @@ 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
|
+
|
186
229
|
#### Interact with Sorbet LSP mode
|
187
230
|
|
188
231
|
**Experimental**
|
@@ -273,7 +316,7 @@ Create an LSP client:
|
|
273
316
|
|
274
317
|
```rb
|
275
318
|
client = Spoom::LSP::Client.new(
|
276
|
-
Spoom::
|
319
|
+
Spoom::Sorbet::BIN_PATH,
|
277
320
|
"--lsp",
|
278
321
|
"--enable-all-experimental-lsp-features",
|
279
322
|
"--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: "Exclude RBI files from 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
|