spoom 1.0.2 → 1.0.7

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: 5c89940fbd779667ff48027cb2c60a2a67752c23bd65b47935d44d69f451065d
4
- data.tar.gz: 12235dfb24ae6578e2fe5299d92311be7bfe424ae810748a70cf32e7235517ea
3
+ metadata.gz: f16907e7c4ce2a3d368bcac828ae7cfb43f0dde8f857bbfa364c4a3a16e0e433
4
+ data.tar.gz: b6d2a532d34b0cd5e8e4964d2edc5e279e5481de511a4e61ea764e120e4bae33
5
5
  SHA512:
6
- metadata.gz: e72516c64841d1395a30ccffcb5ecabe7003ed9277f75e39929cba65bd49174cd0e05e310804dbbe465aa6ab234e1d0c64677a69e4e3f2aa5dfc4eeb323726eb
7
- data.tar.gz: 2da79d80442024d88844ceec77394376fdd71f59fece8c1dff557b2707474794a830101775edf7820370d4a8df9f766e08012c8ed36b6e11f13625cf55f3deb1
6
+ metadata.gz: ad2f822b0c34fdb51ae8002bdc2c3f35202e219e334723716b141afe9ab00b18c65f74c3129cff6e4a9cb992d3c673ccb8afa522114cf2759af5cdd888df5100
7
+ data.tar.gz: f077abc8f9be4b2768776214601dd1c8d8c5709649536202a0ab9765058de9dc8590712b9a6fb96c30a0ac5ed46e7c21d84ab9bff190e48d99d5e0bddab1d44e
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,4 +7,7 @@ gemspec
6
7
 
7
8
  group(:development) do
8
9
  gem('rubocop-shopify', require: false)
10
+ gem('rubocop-sorbet', require: false)
11
+ gem('byebug')
12
+ gem('pry-byebug')
9
13
  end
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
@@ -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
@@ -0,0 +1,7 @@
1
+ #! /usr/bin/env ruby
2
+ # typed: true
3
+ # frozen_string_literal: true
4
+
5
+ require_relative "../lib/spoom"
6
+
7
+ Spoom::Cli::Main.start(ARGV)
@@ -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"
@@ -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,60 @@
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
+ in_sorbet_project!
22
+
23
+ from = options[:from]
24
+ to = options[:to]
25
+ force = options[:force]
26
+
27
+ unless Sorbet::Sigils.valid_strictness?(from)
28
+ say_error("Invalid strictness #{from} for option --from")
29
+ exit(1)
30
+ end
31
+
32
+ unless Sorbet::Sigils.valid_strictness?(to)
33
+ say_error("Invalid strictness #{to} for option --to")
34
+ exit(1)
35
+ end
36
+
37
+ directory = File.expand_path(directory)
38
+ files_to_bump = Sorbet::Sigils.files_with_sigil_strictness(directory, from)
39
+ Sorbet::Sigils.change_sigil_in_files(files_to_bump, to)
40
+
41
+ return if force
42
+
43
+ output, no_errors = Sorbet.srb_tc(path: exec_path, capture_err: true)
44
+
45
+ return if no_errors
46
+
47
+ errors = Sorbet::Errors::Parser.parse_string(output)
48
+
49
+ files_with_errors = errors.map do |err|
50
+ path = File.expand_path(err.file)
51
+ next unless path.start_with?(directory)
52
+ next unless File.file?(path)
53
+ path
54
+ end.compact.uniq
55
+
56
+ Sorbet::Sigils.change_sigil_in_files(files_with_errors, from)
57
+ end
58
+ end
59
+ end
60
+ end