spoom 1.0.4 → 1.0.5

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: d851bf66dbfb8e1d316b27466fde8ee205e55e68b9b489c3f8f234c03e1763d2
4
- data.tar.gz: '068972f0ebb9393400dcbf68837be0a58114cc55560438fd329be3b54acfcaaf'
3
+ metadata.gz: 7a5f19185a1beba98f75c9c96b08c06400c9917c0d85734f1dbf9c9d77e3fa74
4
+ data.tar.gz: 53f4b8b10f81b19588f58d57c93349721230836e3b98524b52c46a78f4682365
5
5
  SHA512:
6
- metadata.gz: 8315d9c7de9beaf2aa9a5d6963cde78ec6e9e7949659bac85a0ff719080755808fb5a854c2a03f6dcab8134c17bc8d90d145d53d32a3f1632d83a2c6a21ebfaa
7
- data.tar.gz: 88fee999fa79caf40dd776ce5253a1337a5acc2507653a2c09adfb3e4723b6a8a06033d34c8f299b3a7a663ef01c2fa4a8243d98fd9f104e9c77ad69f9836ff7
6
+ metadata.gz: aff5a2bc4b3bd01c815ad0d00e76fcc700728ec659135645dce259db72dc97cf8ea2d339827d979bf9f225637b7d23f2ea09d13dd02786229fe5c42caf88886e
7
+ data.tar.gz: b2760f8f58a7f3cbfd90d59e16f5bb9b76356f13fc3f38a606758652f53caf72004024128e4195451ca32f30c9d03c6bdb553a6a7aea2893c7f0e6a2e6ec2528
data/README.md CHANGED
@@ -20,7 +20,218 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- ### Parsing Sorbet config
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
@@ -6,6 +6,7 @@ require "rake/testtask"
6
6
  Rake::TestTask.new(:test) do |t|
7
7
  t.libs << "test"
8
8
  t.libs << "lib"
9
+ t.warning = false
9
10
  t.test_files = FileList["test/**/*_test.rb"]
10
11
  end
11
12
 
@@ -7,7 +7,8 @@ module Spoom
7
7
  class Error < StandardError; end
8
8
  end
9
9
 
10
- require "spoom/cli"
11
10
  require "spoom/config"
11
+
12
12
  require "spoom/sorbet"
13
+ require "spoom/cli"
13
14
  require "spoom/version"
@@ -3,25 +3,60 @@
3
3
 
4
4
  require "thor"
5
5
 
6
- require_relative "cli/commands/config"
7
- require_relative "cli/commands/lsp"
8
- require_relative "cli/commands/run"
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"
9
13
 
10
14
  module Spoom
11
15
  module Cli
12
16
  class Main < Thor
13
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)
14
23
 
15
- class_option :no_color, desc: "Don't use colors", type: :boolean
24
+ desc "bump", "bump Sorbet sigils from `false` to `true` when no errors"
25
+ subcommand "bump", Spoom::Cli::Bump
16
26
 
17
27
  desc "config", "manage Sorbet config"
18
- subcommand "config", Spoom::Cli::Commands::Config
28
+ subcommand "config", Spoom::Cli::Config
29
+
30
+ desc "coverage", "collect metrics related to Sorbet coverage"
31
+ subcommand "coverage", Spoom::Cli::Coverage
19
32
 
20
33
  desc "lsp", "send LSP requests to Sorbet"
21
- subcommand "lsp", Spoom::Cli::Commands::LSP
34
+ subcommand "lsp", Spoom::Cli::LSP
22
35
 
23
36
  desc "tc", "run Sorbet and parses its output"
24
- subcommand "tc", Spoom::Cli::Commands::Run
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
25
60
 
26
61
  # Utils
27
62
 
@@ -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
@@ -0,0 +1,51 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../file_tree"
5
+ require_relative "../sorbet/config"
6
+
7
+ module Spoom
8
+ module Cli
9
+ class Config < Thor
10
+ include Helper
11
+
12
+ default_task :show
13
+
14
+ desc "show", "show Sorbet config"
15
+ def show
16
+ in_sorbet_project!
17
+ config = Spoom::Sorbet::Config.parse_file(sorbet_config)
18
+
19
+ say("Found Sorbet config at `#{sorbet_config}`.")
20
+
21
+ say("\nPaths typechecked:")
22
+ if config.paths.empty?
23
+ say(" * (default: .)")
24
+ else
25
+ config.paths.each do |path|
26
+ say(" * #{path}")
27
+ end
28
+ end
29
+
30
+ say("\nPaths ignored:")
31
+ if config.ignore.empty?
32
+ say(" * (default: none)")
33
+ else
34
+ config.ignore.each do |path|
35
+ say(" * #{path}")
36
+ end
37
+ end
38
+
39
+ say("\nAllowed extensions:")
40
+ if config.allowed_extensions.empty?
41
+ say(" * .rb (default)")
42
+ say(" * .rbi (default)")
43
+ else
44
+ config.allowed_extensions.each do |ext|
45
+ say(" * #{ext}")
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end