spoom 1.0.1 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -1
- data/README.md +253 -1
- data/Rakefile +2 -0
- data/exe/spoom +7 -0
- data/lib/spoom.rb +9 -1
- data/lib/spoom/cli.rb +68 -0
- data/lib/spoom/cli/bump.rb +59 -0
- data/lib/spoom/cli/config.rb +51 -0
- data/lib/spoom/cli/coverage.rb +191 -0
- data/lib/spoom/cli/helper.rb +70 -0
- data/lib/spoom/cli/lsp.rb +165 -0
- data/lib/spoom/cli/run.rb +79 -0
- data/lib/spoom/config.rb +11 -0
- data/lib/spoom/coverage.rb +73 -0
- data/lib/spoom/coverage/d3.rb +110 -0
- data/lib/spoom/coverage/d3/base.rb +50 -0
- data/lib/spoom/coverage/d3/circle_map.rb +195 -0
- data/lib/spoom/coverage/d3/pie.rb +175 -0
- data/lib/spoom/coverage/d3/timeline.rb +486 -0
- data/lib/spoom/coverage/report.rb +308 -0
- data/lib/spoom/coverage/snapshot.rb +132 -0
- data/lib/spoom/file_tree.rb +196 -0
- data/lib/spoom/git.rb +98 -0
- data/lib/spoom/printer.rb +81 -0
- data/lib/spoom/sorbet.rb +83 -0
- data/lib/spoom/sorbet/config.rb +21 -9
- data/lib/spoom/sorbet/errors.rb +139 -0
- data/lib/spoom/sorbet/lsp.rb +196 -0
- data/lib/spoom/sorbet/lsp/base.rb +58 -0
- data/lib/spoom/sorbet/lsp/errors.rb +45 -0
- data/lib/spoom/sorbet/lsp/structures.rb +312 -0
- data/lib/spoom/sorbet/metrics.rb +33 -0
- data/lib/spoom/sorbet/sigils.rb +98 -0
- data/lib/spoom/test_helpers/project.rb +103 -0
- data/lib/spoom/timeline.rb +53 -0
- data/lib/spoom/version.rb +2 -1
- data/templates/card.erb +8 -0
- data/templates/card_snapshot.erb +22 -0
- data/templates/page.erb +50 -0
- metadata +80 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b9a6d7f3818e0af29439ba291b6c05fa29a821de374ee5c8181c64a05f3f7a3
|
4
|
+
data.tar.gz: 6d60e6fc252e6aebcfff2860778b1e2ac596740823a279aec1788ccaefa2fc4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d156b4d9c8f2edb2f68e1b5fc21b659d8bec0bc60fd9110f565889a620febce064cc3ee176228cd659f1b21ca0ab000a9790407537eb9bd18edbc41d601b963b
|
7
|
+
data.tar.gz: a7e1bf03e8bd942bc0f2ac6379739bfd795d1642025e00ef33e198b6422c61598b23c753248a698568b7c1edde23d232604b76ccdfd9d1b7ef98139c74cc583a
|
data/Gemfile
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
source "https://rubygems.org"
|
@@ -6,5 +7,7 @@ gemspec
|
|
6
7
|
|
7
8
|
group(:development) do
|
8
9
|
gem('rubocop-shopify', require: false)
|
9
|
-
gem(
|
10
|
+
gem('rubocop-sorbet', require: false)
|
11
|
+
gem('byebug')
|
12
|
+
gem('pry-byebug')
|
10
13
|
end
|
data/README.md
CHANGED
@@ -20,7 +20,218 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
`spoom` provides both a CLI and an API to interact with Sorbet.
|
24
|
+
|
25
|
+
### Generate a typing coverage report
|
26
|
+
|
27
|
+
Spoom can create a typing coverage report from Sorbet and Git data:
|
28
|
+
|
29
|
+
![Coverage Report](docs/report.png)
|
30
|
+
|
31
|
+
After installing the `spoom` gem, run the `timeline` command to collect the history data:
|
32
|
+
|
33
|
+
```
|
34
|
+
$ spoom coverage timeline --save
|
35
|
+
```
|
36
|
+
|
37
|
+
Then create the HTML page with `report`:
|
38
|
+
|
39
|
+
```
|
40
|
+
$ spoom coverage report
|
41
|
+
```
|
42
|
+
|
43
|
+
Your report will be generated under `spoom_report.html`.
|
44
|
+
|
45
|
+
See all the [Typing Coverage](#typing-coverage) CLI commands for more details.
|
46
|
+
|
47
|
+
### Command Line Interface
|
48
|
+
|
49
|
+
#### Sorbet configuration commands
|
50
|
+
|
51
|
+
Spoom works with your `sorbet/config` file. No additional configuration is needed.
|
52
|
+
|
53
|
+
Show Sorbet config options:
|
54
|
+
|
55
|
+
```
|
56
|
+
$ spoom config
|
57
|
+
```
|
58
|
+
|
59
|
+
#### Listing files
|
60
|
+
|
61
|
+
List the files (and related strictness) that will be typchecked with the current Sorbet config options:
|
62
|
+
|
63
|
+
```
|
64
|
+
$ spoom files
|
65
|
+
```
|
66
|
+
|
67
|
+
#### Errors sorting and filtering
|
68
|
+
|
69
|
+
List all typechecking errors sorted by location:
|
70
|
+
|
71
|
+
```
|
72
|
+
$ spoom tc -s
|
73
|
+
```
|
74
|
+
|
75
|
+
List all typechecking errors sorted by error code first:
|
76
|
+
|
77
|
+
```
|
78
|
+
$ spoom tc -s code
|
79
|
+
```
|
80
|
+
|
81
|
+
List only typechecking errors from a specific error code:
|
82
|
+
|
83
|
+
```
|
84
|
+
$ spoom tc -c 7004
|
85
|
+
```
|
86
|
+
|
87
|
+
List only the first 10 typechecking errors
|
88
|
+
|
89
|
+
```
|
90
|
+
$ spoom tc -l 10
|
91
|
+
```
|
92
|
+
|
93
|
+
These options can be combined:
|
94
|
+
|
95
|
+
```
|
96
|
+
$ spoom tc -s -c 7004 -l 10
|
97
|
+
```
|
98
|
+
|
99
|
+
#### Typing coverage
|
100
|
+
|
101
|
+
Show metrics about the project contents and the typing coverage:
|
102
|
+
|
103
|
+
```
|
104
|
+
$ spoom coverage
|
105
|
+
```
|
106
|
+
|
107
|
+
Save coverage data under `spoom_data/`:
|
108
|
+
|
109
|
+
```
|
110
|
+
$ spoom coverage --save
|
111
|
+
```
|
112
|
+
|
113
|
+
Save coverage data under a specific directory:
|
114
|
+
|
115
|
+
```
|
116
|
+
$ spoom coverage --save my_data/
|
117
|
+
```
|
118
|
+
|
119
|
+
Show typing coverage evolution based on the commits history:
|
120
|
+
|
121
|
+
```
|
122
|
+
$ spoom coverage timeline
|
123
|
+
```
|
124
|
+
|
125
|
+
Show typing coverage evolution based on the commits history between specific dates:
|
126
|
+
|
127
|
+
```
|
128
|
+
$ spoom coverage timeline --from YYYY-MM-DD --to YYYY-MM-DD
|
129
|
+
```
|
130
|
+
|
131
|
+
Save the typing coverage evolution as JSON under `spoom_data/`:
|
132
|
+
|
133
|
+
```
|
134
|
+
$ spoom coverage timeline --save
|
135
|
+
```
|
136
|
+
|
137
|
+
Save the typing coverage evolution as JSON in a specific directory:
|
138
|
+
|
139
|
+
```
|
140
|
+
$ spoom coverage timeline --save my_data/
|
141
|
+
```
|
142
|
+
|
143
|
+
Run `bundle install` for each commit of the timeline (may solve errors due to different Sorbet versions):
|
144
|
+
|
145
|
+
```
|
146
|
+
$ spoom coverage timeline --bundle-install
|
147
|
+
```
|
148
|
+
|
149
|
+
Generate an HTML typing coverage report:
|
150
|
+
|
151
|
+
```
|
152
|
+
$ spoom coverage report
|
153
|
+
```
|
154
|
+
|
155
|
+
Change the colors used for strictnesses (useful for colorblind folks):
|
156
|
+
|
157
|
+
```
|
158
|
+
$ spoom coverage report \
|
159
|
+
--color-true "#648ffe" \
|
160
|
+
--color-false "#fe6002" \
|
161
|
+
--color-ignore "#feb000" \
|
162
|
+
--color-strict "#795ef0" \
|
163
|
+
--color-strong "#6444f1"
|
164
|
+
```
|
165
|
+
|
166
|
+
Open the HTML typing coverage report:
|
167
|
+
|
168
|
+
```
|
169
|
+
$ spoom coverage open
|
170
|
+
```
|
171
|
+
|
172
|
+
#### Change the sigil used in files
|
173
|
+
|
174
|
+
Bump the strictness from all files currently at `typed: false` to `typed: true` where it does not create typechecking errors:
|
175
|
+
|
176
|
+
```
|
177
|
+
$ spoom bump --from false --to true
|
178
|
+
```
|
179
|
+
|
180
|
+
Bump the strictness from all files currently at `typed: false` to `typed: true` even if it creates typechecking errors:
|
181
|
+
|
182
|
+
```
|
183
|
+
$ spoom bump --from false --to true -f
|
184
|
+
```
|
185
|
+
|
186
|
+
#### Interact with Sorbet LSP mode
|
187
|
+
|
188
|
+
**Experimental**
|
189
|
+
|
190
|
+
Find all definitions for `Foo`:
|
191
|
+
|
192
|
+
```
|
193
|
+
$ spoom lsp find Foo
|
194
|
+
```
|
195
|
+
|
196
|
+
List all symbols in a file:
|
197
|
+
|
198
|
+
```
|
199
|
+
$ spoom lsp symbols <file.rb>
|
200
|
+
```
|
201
|
+
|
202
|
+
List all definitions for a specific code location:
|
203
|
+
|
204
|
+
```
|
205
|
+
$ spoom lsp defs <file.rb> <line> <column>
|
206
|
+
```
|
207
|
+
|
208
|
+
List all references for a specific code location:
|
209
|
+
|
210
|
+
```
|
211
|
+
$ spoom lsp refs <file.rb> <line> <column>
|
212
|
+
```
|
213
|
+
|
214
|
+
Show hover information for a specific code location:
|
215
|
+
|
216
|
+
```
|
217
|
+
$ spoom lsp hover <file.rb> <line> <column>
|
218
|
+
```
|
219
|
+
|
220
|
+
Show signature information for a specific code location:
|
221
|
+
|
222
|
+
```
|
223
|
+
$ spoom lsp sig <file.rb> <line> <column>
|
224
|
+
```
|
225
|
+
|
226
|
+
Show type information for a specific code location:
|
227
|
+
|
228
|
+
```
|
229
|
+
$ spoom lsp sig <file.rb> <line> <column>
|
230
|
+
```
|
231
|
+
|
232
|
+
### API
|
233
|
+
|
234
|
+
#### Parsing Sorbet config
|
24
235
|
|
25
236
|
Parses a Sorbet config file:
|
26
237
|
|
@@ -41,6 +252,47 @@ puts config.paths # "a", "b"
|
|
41
252
|
puts config.ignore # "c"
|
42
253
|
```
|
43
254
|
|
255
|
+
List all files typchecked by Sorbet:
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
config = Spoom::Sorbet::Config.parse_file("sorbet/config")
|
259
|
+
puts Spoom::Sorbet.srb_files(config)
|
260
|
+
```
|
261
|
+
|
262
|
+
#### Parsing Sorbet metrics
|
263
|
+
|
264
|
+
Display metrics collected during typechecking:
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
puts Spoom::Sorbet.srb_metrics(capture_err: false)
|
268
|
+
```
|
269
|
+
|
270
|
+
#### Interacting with LSP
|
271
|
+
|
272
|
+
Create an LSP client:
|
273
|
+
|
274
|
+
```rb
|
275
|
+
client = Spoom::LSP::Client.new(
|
276
|
+
Spoom::Config::SORBET_PATH,
|
277
|
+
"--lsp",
|
278
|
+
"--enable-all-experimental-lsp-features",
|
279
|
+
"--disable-watchman",
|
280
|
+
)
|
281
|
+
client.open(".")
|
282
|
+
```
|
283
|
+
|
284
|
+
Find all the symbols matching a string:
|
285
|
+
|
286
|
+
```rb
|
287
|
+
puts client.symbols("Foo")
|
288
|
+
```
|
289
|
+
|
290
|
+
Find all the symbols for a file:
|
291
|
+
|
292
|
+
```rb
|
293
|
+
puts client.document_symbols("file://path/to/my/file.rb")
|
294
|
+
```
|
295
|
+
|
44
296
|
## Development
|
45
297
|
|
46
298
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. Don't forget to run `bin/sanity` before pushing your changes.
|
data/Rakefile
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require "bundler/gem_tasks"
|
3
4
|
require "rake/testtask"
|
@@ -5,6 +6,7 @@ require "rake/testtask"
|
|
5
6
|
Rake::TestTask.new(:test) do |t|
|
6
7
|
t.libs << "test"
|
7
8
|
t.libs << "lib"
|
9
|
+
t.warning = false
|
8
10
|
t.test_files = FileList["test/**/*_test.rb"]
|
9
11
|
end
|
10
12
|
|
data/exe/spoom
CHANGED
data/lib/spoom.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require "sorbet-runtime"
|
4
5
|
|
6
|
+
module Spoom
|
7
|
+
class Error < StandardError; end
|
8
|
+
end
|
9
|
+
|
10
|
+
require "spoom/config"
|
11
|
+
|
12
|
+
require "spoom/sorbet"
|
13
|
+
require "spoom/cli"
|
5
14
|
require "spoom/version"
|
6
|
-
require "spoom/sorbet/config"
|
data/lib/spoom/cli.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
require_relative 'cli/helper'
|
7
|
+
|
8
|
+
require_relative "cli/bump"
|
9
|
+
require_relative "cli/config"
|
10
|
+
require_relative "cli/lsp"
|
11
|
+
require_relative "cli/coverage"
|
12
|
+
require_relative "cli/run"
|
13
|
+
|
14
|
+
module Spoom
|
15
|
+
module Cli
|
16
|
+
class Main < Thor
|
17
|
+
extend T::Sig
|
18
|
+
include Helper
|
19
|
+
|
20
|
+
class_option :color, desc: "Use colors", type: :boolean, default: true
|
21
|
+
class_option :path, desc: "Run spoom in a specific path", type: :string, default: ".", aliases: :p
|
22
|
+
map T.unsafe(%w[--version -v] => :__print_version)
|
23
|
+
|
24
|
+
desc "bump", "bump Sorbet sigils from `false` to `true` when no errors"
|
25
|
+
subcommand "bump", Spoom::Cli::Bump
|
26
|
+
|
27
|
+
desc "config", "manage Sorbet config"
|
28
|
+
subcommand "config", Spoom::Cli::Config
|
29
|
+
|
30
|
+
desc "coverage", "collect metrics related to Sorbet coverage"
|
31
|
+
subcommand "coverage", Spoom::Cli::Coverage
|
32
|
+
|
33
|
+
desc "lsp", "send LSP requests to Sorbet"
|
34
|
+
subcommand "lsp", Spoom::Cli::LSP
|
35
|
+
|
36
|
+
desc "tc", "run Sorbet and parses its output"
|
37
|
+
subcommand "tc", Spoom::Cli::Run
|
38
|
+
|
39
|
+
desc "files", "list all the files typechecked by Sorbet"
|
40
|
+
def files
|
41
|
+
in_sorbet_project!
|
42
|
+
|
43
|
+
path = exec_path
|
44
|
+
config = Spoom::Sorbet::Config.parse_file(sorbet_config)
|
45
|
+
files = Spoom::Sorbet.srb_files(config, path: path)
|
46
|
+
|
47
|
+
say("Files matching `#{sorbet_config}`:")
|
48
|
+
if files.empty?
|
49
|
+
say(" NONE")
|
50
|
+
else
|
51
|
+
tree = FileTree.new(files, strip_prefix: path)
|
52
|
+
tree.print(colors: options[:color], indent_level: 2)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "--version", "show version"
|
57
|
+
def __print_version
|
58
|
+
puts "Spoom v#{Spoom::VERSION}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Utils
|
62
|
+
|
63
|
+
def self.exit_on_failure?
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'find'
|
5
|
+
require 'open3'
|
6
|
+
|
7
|
+
module Spoom
|
8
|
+
module Cli
|
9
|
+
class Bump < Thor
|
10
|
+
extend T::Sig
|
11
|
+
include Helper
|
12
|
+
|
13
|
+
default_task :bump
|
14
|
+
|
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
|
+
option :to, type: :string, default: Spoom::Sorbet::Sigils::STRICTNESS_TRUE
|
18
|
+
option :force, desc: "change strictness without type checking", type: :boolean, default: false, aliases: :f
|
19
|
+
sig { params(directory: String).void }
|
20
|
+
def bump(directory = ".")
|
21
|
+
from = options[:from]
|
22
|
+
to = options[:to]
|
23
|
+
force = options[:force]
|
24
|
+
|
25
|
+
unless Sorbet::Sigils.valid_strictness?(from)
|
26
|
+
say_error("Invalid strictness #{from} for option --from")
|
27
|
+
exit(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
unless Sorbet::Sigils.valid_strictness?(to)
|
31
|
+
say_error("Invalid strictness #{to} for option --to")
|
32
|
+
exit(1)
|
33
|
+
end
|
34
|
+
|
35
|
+
files_to_bump = Sorbet::Sigils.files_with_sigil_strictness(directory, from)
|
36
|
+
|
37
|
+
Sorbet::Sigils.change_sigil_in_files(files_to_bump, to)
|
38
|
+
|
39
|
+
return [] if force
|
40
|
+
|
41
|
+
output, no_errors = Sorbet.srb_tc(path: File.expand_path(directory), capture_err: true)
|
42
|
+
|
43
|
+
return [] if no_errors
|
44
|
+
|
45
|
+
errors = Sorbet::Errors::Parser.parse_string(output)
|
46
|
+
|
47
|
+
files_with_errors = errors.map do |err|
|
48
|
+
path = err.file
|
49
|
+
File.join(directory, path) if path && File.file?(path)
|
50
|
+
end.compact.uniq
|
51
|
+
|
52
|
+
Sorbet::Sigils.change_sigil_in_files(files_with_errors, from)
|
53
|
+
end
|
54
|
+
|
55
|
+
no_commands do
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|