spoom 1.1.15 → 1.2.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.
@@ -0,0 +1,121 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Spoom
5
+ module Git
6
+ class Commit < T::Struct
7
+ extend T::Sig
8
+
9
+ class << self
10
+ extend T::Sig
11
+
12
+ # Parse a line formated as `%h %at` into a `Commit`
13
+ sig { params(string: String).returns(T.nilable(Commit)) }
14
+ def parse_line(string)
15
+ sha, epoch = string.split(" ", 2)
16
+ return nil unless sha && epoch
17
+
18
+ time = Time.strptime(epoch, "%s")
19
+ Commit.new(sha: sha, time: time)
20
+ end
21
+ end
22
+
23
+ const :sha, String
24
+ const :time, Time
25
+
26
+ sig { returns(Integer) }
27
+ def timestamp
28
+ time.to_i
29
+ end
30
+ end
31
+ end
32
+
33
+ class Context
34
+ # Git features for a context
35
+ module Git
36
+ extend T::Sig
37
+ extend T::Helpers
38
+
39
+ requires_ancestor { Context }
40
+
41
+ # Run a command prefixed by `git` in this context directory
42
+ sig { params(command: String).returns(ExecResult) }
43
+ def git(command)
44
+ exec("git #{command}")
45
+ end
46
+
47
+ # Run `git init` in this context directory
48
+ #
49
+ # Warning: passing a branch will run `git init -b <branch>` which is only available in git 2.28+.
50
+ # In older versions, use `git_init!` followed by `git("checkout -b <branch>")`.
51
+ sig { params(branch: T.nilable(String)).returns(ExecResult) }
52
+ def git_init!(branch: nil)
53
+ if branch
54
+ git("init -b #{branch}")
55
+ else
56
+ git("init")
57
+ end
58
+ end
59
+
60
+ # Run `git checkout` in this context directory
61
+ sig { params(ref: String).returns(ExecResult) }
62
+ def git_checkout!(ref: "main")
63
+ git("checkout #{ref}")
64
+ end
65
+
66
+ # Run `git add . && git commit` in this context directory
67
+ sig { params(message: String, time: Time, allow_empty: T::Boolean).void }
68
+ def git_commit!(message: "message", time: Time.now.utc, allow_empty: false)
69
+ git("add --all")
70
+
71
+ args = ["-m '#{message}'", "--date '#{time}'"]
72
+ args << "--allow-empty" if allow_empty
73
+
74
+ exec("GIT_COMMITTER_DATE=\"#{time}\" git -c commit.gpgsign=false commit #{args.join(" ")}")
75
+ end
76
+
77
+ # Get the current git branch in this context directory
78
+ sig { returns(T.nilable(String)) }
79
+ def git_current_branch
80
+ res = git("branch --show-current")
81
+ return nil unless res.status
82
+
83
+ res.out.strip
84
+ end
85
+
86
+ # Run `git diff` in this context directory
87
+ sig { params(arg: String).returns(ExecResult) }
88
+ def git_diff(*arg)
89
+ git("diff #{arg.join(" ")}")
90
+ end
91
+
92
+ # Get the last commit in the currently checked out branch
93
+ sig { params(short_sha: T::Boolean).returns(T.nilable(Spoom::Git::Commit)) }
94
+ def git_last_commit(short_sha: true)
95
+ res = git_log("HEAD --format='%#{short_sha ? "h" : "H"} %at' -1")
96
+ return nil unless res.status
97
+
98
+ out = res.out.strip
99
+ return nil if out.empty?
100
+
101
+ Spoom::Git::Commit.parse_line(out)
102
+ end
103
+
104
+ sig { params(arg: String).returns(ExecResult) }
105
+ def git_log(*arg)
106
+ git("log #{arg.join(" ")}")
107
+ end
108
+
109
+ sig { params(arg: String).returns(ExecResult) }
110
+ def git_show(*arg)
111
+ git("show #{arg.join(" ")}")
112
+ end
113
+
114
+ # Is there uncommited changes in this context directory?
115
+ sig { params(path: String).returns(T::Boolean) }
116
+ def git_workdir_clean?(path: ".")
117
+ git_diff("HEAD").out.empty?
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,136 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Spoom
5
+ class Context
6
+ # Sorbet features for a context
7
+ module Sorbet
8
+ extend T::Sig
9
+ extend T::Helpers
10
+
11
+ requires_ancestor { Context }
12
+
13
+ # Run `bundle exec srb` in this context directory
14
+ sig { params(arg: String, sorbet_bin: T.nilable(String), capture_err: T::Boolean).returns(ExecResult) }
15
+ def srb(*arg, sorbet_bin: nil, capture_err: true)
16
+ res = if sorbet_bin
17
+ exec("#{sorbet_bin} #{arg.join(" ")}", capture_err: capture_err)
18
+ else
19
+ bundle_exec("srb #{arg.join(" ")}", capture_err: capture_err)
20
+ end
21
+
22
+ case res.exit_code
23
+ when Spoom::Sorbet::KILLED_CODE
24
+ raise Spoom::Sorbet::Error::Killed.new("Sorbet was killed.", res)
25
+ when Spoom::Sorbet::SEGFAULT_CODE
26
+ raise Spoom::Sorbet::Error::Segfault.new("Sorbet segfaulted.", res)
27
+ end
28
+
29
+ res
30
+ end
31
+
32
+ sig { params(arg: String, sorbet_bin: T.nilable(String), capture_err: T::Boolean).returns(ExecResult) }
33
+ def srb_tc(*arg, sorbet_bin: nil, capture_err: true)
34
+ arg.prepend("tc") unless sorbet_bin
35
+ T.unsafe(self).srb(*arg, sorbet_bin: sorbet_bin, capture_err: capture_err)
36
+ end
37
+
38
+ sig do
39
+ params(
40
+ arg: String,
41
+ sorbet_bin: T.nilable(String),
42
+ capture_err: T::Boolean,
43
+ ).returns(T.nilable(T::Hash[String, Integer]))
44
+ end
45
+ def srb_metrics(*arg, sorbet_bin: nil, capture_err: true)
46
+ metrics_file = "metrics.tmp"
47
+
48
+ T.unsafe(self).srb_tc(
49
+ "--metrics-file",
50
+ metrics_file,
51
+ *arg,
52
+ sorbet_bin: sorbet_bin,
53
+ capture_err: capture_err,
54
+ )
55
+ return nil unless file?(metrics_file)
56
+
57
+ metrics_path = absolute_path_to(metrics_file)
58
+ metrics = Spoom::Sorbet::MetricsParser.parse_file(metrics_path)
59
+ remove!(metrics_file)
60
+ metrics
61
+ end
62
+
63
+ # List all files typechecked by Sorbet from its `config`
64
+ sig { params(with_config: T.nilable(Spoom::Sorbet::Config)).returns(T::Array[String]) }
65
+ def srb_files(with_config: nil)
66
+ config = with_config || sorbet_config
67
+ regs = config.ignore.map { |string| Regexp.new(Regexp.escape(string)) }
68
+ exts = config.allowed_extensions.empty? ? [".rb", ".rbi"] : config.allowed_extensions
69
+ glob("**/*{#{exts.join(",")}}").reject do |f|
70
+ regs.any? { |re| re.match?(f) }
71
+ end.sort
72
+ end
73
+
74
+ sig { params(arg: String, sorbet_bin: T.nilable(String), capture_err: T::Boolean).returns(T.nilable(String)) }
75
+ def srb_version(*arg, sorbet_bin: nil, capture_err: true)
76
+ res = T.unsafe(self).srb_tc("--no-config", "--version", *arg, sorbet_bin: sorbet_bin, capture_err: capture_err)
77
+ return nil unless res.status
78
+
79
+ res.out.split(" ")[2]
80
+ end
81
+
82
+ # Does this context has a `sorbet/config` file?
83
+ sig { returns(T::Boolean) }
84
+ def has_sorbet_config?
85
+ file?(Spoom::Sorbet::CONFIG_PATH)
86
+ end
87
+
88
+ sig { returns(Spoom::Sorbet::Config) }
89
+ def sorbet_config
90
+ Spoom::Sorbet::Config.parse_string(read_sorbet_config)
91
+ end
92
+
93
+ # Read the contents of `sorbet/config` in this context directory
94
+ sig { returns(String) }
95
+ def read_sorbet_config
96
+ read(Spoom::Sorbet::CONFIG_PATH)
97
+ end
98
+
99
+ # Set the `contents` of `sorbet/config` in this context directory
100
+ sig { params(contents: String, append: T::Boolean).void }
101
+ def write_sorbet_config!(contents, append: false)
102
+ write!(Spoom::Sorbet::CONFIG_PATH, contents, append: append)
103
+ end
104
+
105
+ # Read the strictness sigil from the file at `relative_path` (returns `nil` if no sigil)
106
+ sig { params(relative_path: String).returns(T.nilable(String)) }
107
+ def read_file_strictness(relative_path)
108
+ Spoom::Sorbet::Sigils.file_strictness(absolute_path_to(relative_path))
109
+ end
110
+
111
+ # Get the commit introducing the `sorbet/config` file
112
+ sig { returns(T.nilable(Spoom::Git::Commit)) }
113
+ def sorbet_intro_commit
114
+ res = git_log("--diff-filter=A --format='%h %at' -1 -- sorbet/config")
115
+ return nil unless res.status
116
+
117
+ out = res.out.strip
118
+ return nil if out.empty?
119
+
120
+ Spoom::Git::Commit.parse_line(out)
121
+ end
122
+
123
+ # Get the commit removing the `sorbet/config` file
124
+ sig { returns(T.nilable(Spoom::Git::Commit)) }
125
+ def sorbet_removal_commit
126
+ res = git_log("--diff-filter=D --format='%h %at' -1 -- sorbet/config")
127
+ return nil unless res.status
128
+
129
+ out = res.out.strip
130
+ return nil if out.empty?
131
+
132
+ Spoom::Git::Commit.parse_line(out)
133
+ end
134
+ end
135
+ end
136
+ end
data/lib/spoom/context.rb CHANGED
@@ -3,6 +3,14 @@
3
3
 
4
4
  require "fileutils"
5
5
  require "open3"
6
+ require "time"
7
+ require "tmpdir"
8
+
9
+ require_relative "context/bundle"
10
+ require_relative "context/exec"
11
+ require_relative "context/file_system"
12
+ require_relative "context/git"
13
+ require_relative "context/sorbet"
6
14
 
7
15
  module Spoom
8
16
  # An abstraction to a Ruby project context
@@ -12,9 +20,11 @@ module Spoom
12
20
  class Context
13
21
  extend T::Sig
14
22
 
15
- # The absolute path to the directory this context is about
16
- sig { returns(String) }
17
- attr_reader :absolute_path
23
+ include Bundle
24
+ include Exec
25
+ include FileSystem
26
+ include Git
27
+ include Sorbet
18
28
 
19
29
  class << self
20
30
  extend T::Sig
@@ -29,6 +39,10 @@ module Spoom
29
39
  end
30
40
  end
31
41
 
42
+ # The absolute path to the directory this context is about
43
+ sig { returns(String) }
44
+ attr_reader :absolute_path
45
+
32
46
  # Create a new context about `absolute_path`
33
47
  #
34
48
  # The directory will not be created if it doesn't exist.
@@ -37,195 +51,5 @@ module Spoom
37
51
  def initialize(absolute_path)
38
52
  @absolute_path = T.let(::File.expand_path(absolute_path), String)
39
53
  end
40
-
41
- # Returns the absolute path to `relative_path` in the context's directory
42
- sig { params(relative_path: String).returns(String) }
43
- def absolute_path_to(relative_path)
44
- File.join(@absolute_path, relative_path)
45
- end
46
-
47
- # File System
48
-
49
- # Does the context directory at `absolute_path` exist and is a directory?
50
- sig { returns(T::Boolean) }
51
- def exist?
52
- File.directory?(@absolute_path)
53
- end
54
-
55
- # Create the context directory at `absolute_path`
56
- sig { void }
57
- def mkdir!
58
- FileUtils.rm_rf(@absolute_path)
59
- FileUtils.mkdir_p(@absolute_path)
60
- end
61
-
62
- # List all files in this context matching `pattern`
63
- sig { params(pattern: String).returns(T::Array[String]) }
64
- def glob(pattern = "**/*")
65
- Dir.glob(absolute_path_to(pattern)).map do |path|
66
- Pathname.new(path).relative_path_from(@absolute_path).to_s
67
- end.sort
68
- end
69
-
70
- # List all files at the top level of this context directory
71
- sig { returns(T::Array[String]) }
72
- def list
73
- glob("*")
74
- end
75
-
76
- # Does `relative_path` point to an existing file in this context directory?
77
- sig { params(relative_path: String).returns(T::Boolean) }
78
- def file?(relative_path)
79
- File.file?(absolute_path_to(relative_path))
80
- end
81
-
82
- # Return the contents of the file at `relative_path` in this context directory
83
- #
84
- # Will raise if the file doesn't exist.
85
- sig { params(relative_path: String).returns(String) }
86
- def read(relative_path)
87
- File.read(absolute_path_to(relative_path))
88
- end
89
-
90
- # Write `contents` in the file at `relative_path` in this context directory
91
- #
92
- # Append to the file if `append` is true.
93
- sig { params(relative_path: String, contents: String, append: T::Boolean).void }
94
- def write!(relative_path, contents = "", append: false)
95
- absolute_path = absolute_path_to(relative_path)
96
- FileUtils.mkdir_p(File.dirname(absolute_path))
97
- File.write(absolute_path, contents, mode: append ? "a" : "w")
98
- end
99
-
100
- # Remove the path at `relative_path` (recursive + force) in this context directory
101
- sig { params(relative_path: String).void }
102
- def remove!(relative_path)
103
- FileUtils.rm_rf(absolute_path_to(relative_path))
104
- end
105
-
106
- # Move the file or directory from `from_relative_path` to `to_relative_path`
107
- sig { params(from_relative_path: String, to_relative_path: String).void }
108
- def move!(from_relative_path, to_relative_path)
109
- destination_path = absolute_path_to(to_relative_path)
110
- FileUtils.mkdir_p(File.dirname(destination_path))
111
- FileUtils.mv(absolute_path_to(from_relative_path), destination_path)
112
- end
113
-
114
- # Delete this context and its content
115
- #
116
- # Warning: it will `rm -rf` the context directory on the file system.
117
- sig { void }
118
- def destroy!
119
- FileUtils.rm_rf(@absolute_path)
120
- end
121
-
122
- # Execution
123
-
124
- # Run a command in this context directory
125
- sig { params(command: String, capture_err: T::Boolean).returns(ExecResult) }
126
- def exec(command, capture_err: true)
127
- Bundler.with_unbundled_env do
128
- opts = T.let({ chdir: @absolute_path }, T::Hash[Symbol, T.untyped])
129
-
130
- if capture_err
131
- out, err, status = Open3.capture3(command, opts)
132
- ExecResult.new(out: out, err: err, status: T.must(status.success?), exit_code: T.must(status.exitstatus))
133
- else
134
- out, status = Open3.capture2(command, opts)
135
- ExecResult.new(out: out, err: "", status: T.must(status.success?), exit_code: T.must(status.exitstatus))
136
- end
137
- end
138
- end
139
-
140
- # Bundle
141
-
142
- # Read the `contents` of the Gemfile in this context directory
143
- sig { returns(T.nilable(String)) }
144
- def read_gemfile
145
- read("Gemfile")
146
- end
147
-
148
- # Set the `contents` of the Gemfile in this context directory
149
- sig { params(contents: String, append: T::Boolean).void }
150
- def write_gemfile!(contents, append: false)
151
- write!("Gemfile", contents, append: append)
152
- end
153
-
154
- # Run a command with `bundle` in this context directory
155
- sig { params(command: String, version: T.nilable(String)).returns(ExecResult) }
156
- def bundle(command, version: nil)
157
- command = "_#{version}_ #{command}" if version
158
- exec("bundle #{command}")
159
- end
160
-
161
- # Run `bundle install` in this context directory
162
- sig { params(version: T.nilable(String)).returns(ExecResult) }
163
- def bundle_install!(version: nil)
164
- bundle("install", version: version)
165
- end
166
-
167
- # Run a command `bundle exec` in this context directory
168
- sig { params(command: String, version: T.nilable(String)).returns(ExecResult) }
169
- def bundle_exec(command, version: nil)
170
- bundle("exec #{command}", version: version)
171
- end
172
-
173
- # Git
174
-
175
- # Run a command prefixed by `git` in this context directory
176
- sig { params(command: String).returns(ExecResult) }
177
- def git(command)
178
- exec("git #{command}")
179
- end
180
-
181
- # Run `git init` in this context directory
182
- sig { params(branch: String).void }
183
- def git_init!(branch: "main")
184
- git("init -q -b #{branch}")
185
- end
186
-
187
- # Run `git checkout` in this context directory
188
- sig { params(ref: String).returns(ExecResult) }
189
- def git_checkout!(ref: "main")
190
- git("checkout #{ref}")
191
- end
192
-
193
- # Get the current git branch in this context directory
194
- sig { returns(T.nilable(String)) }
195
- def git_current_branch
196
- Spoom::Git.current_branch(path: @absolute_path)
197
- end
198
-
199
- # Get the last commit in the currently checked out branch
200
- sig { params(short_sha: T::Boolean).returns(T.nilable(Git::Commit)) }
201
- def git_last_commit(short_sha: true)
202
- Spoom::Git.last_commit(path: @absolute_path, short_sha: short_sha)
203
- end
204
-
205
- # Sorbet
206
-
207
- # Run `bundle exec srb` in this context directory
208
- sig { params(command: String).returns(ExecResult) }
209
- def srb(command)
210
- bundle_exec("srb #{command}")
211
- end
212
-
213
- # Read the contents of `sorbet/config` in this context directory
214
- sig { returns(String) }
215
- def read_sorbet_config
216
- read(Spoom::Sorbet::CONFIG_PATH)
217
- end
218
-
219
- # Set the `contents` of `sorbet/config` in this context directory
220
- sig { params(contents: String, append: T::Boolean).void }
221
- def write_sorbet_config!(contents, append: false)
222
- write!(Spoom::Sorbet::CONFIG_PATH, contents, append: append)
223
- end
224
-
225
- # Read the strictness sigil from the file at `relative_path` (returns `nil` if no sigil)
226
- sig { params(relative_path: String).returns(T.nilable(String)) }
227
- def read_file_strictness(relative_path)
228
- Spoom::Sorbet::Sigils.file_strictness(absolute_path_to(relative_path))
229
- end
230
54
  end
231
55
  end
@@ -147,7 +147,7 @@ module Spoom
147
147
  def print_map(hash, total)
148
148
  indent
149
149
  hash.each do |key, value|
150
- next unless value > 0
150
+ next if value <= 0
151
151
 
152
152
  printl("#{key}: #{value}#{percent(value, total)}")
153
153
  end
@@ -12,9 +12,9 @@ module Spoom
12
12
  class << self
13
13
  extend T::Sig
14
14
 
15
- sig { params(path: String, rbi: T::Boolean, sorbet_bin: T.nilable(String)).returns(Snapshot) }
16
- def snapshot(path: ".", rbi: true, sorbet_bin: nil)
17
- config = sorbet_config(path: path)
15
+ sig { params(context: Context, rbi: T::Boolean, sorbet_bin: T.nilable(String)).returns(Snapshot) }
16
+ def snapshot(context, rbi: true, sorbet_bin: nil)
17
+ config = context.sorbet_config
18
18
  config.allowed_extensions.push(".rb", ".rbi") if config.allowed_extensions.empty?
19
19
 
20
20
  new_config = config.copy
@@ -27,25 +27,16 @@ module Spoom
27
27
  new_config.options_string,
28
28
  ]
29
29
 
30
- metrics = Spoom::Sorbet.srb_metrics(
31
- *flags,
32
- path: path,
33
- capture_err: true,
34
- sorbet_bin: sorbet_bin,
35
- )
30
+ metrics = context.srb_metrics(*flags, sorbet_bin: sorbet_bin)
31
+
36
32
  # Collect extra information using a different configuration
37
33
  flags << "--ignore sorbet/rbi/"
38
- metrics_without_rbis = Spoom::Sorbet.srb_metrics(
39
- *flags,
40
- path: path,
41
- capture_err: true,
42
- sorbet_bin: sorbet_bin,
43
- )
34
+ metrics_without_rbis = context.srb_metrics(*flags, sorbet_bin: sorbet_bin)
44
35
 
45
36
  snapshot = Snapshot.new
46
37
  return snapshot unless metrics
47
38
 
48
- last_commit = Spoom::Git.last_commit(path: path)
39
+ last_commit = context.git_last_commit
49
40
  snapshot.commit_sha = last_commit&.sha
50
41
  snapshot.commit_timestamp = last_commit&.timestamp
51
42
 
@@ -63,8 +54,10 @@ module Spoom
63
54
 
64
55
  if metrics_without_rbis
65
56
  snapshot.methods_with_sig_excluding_rbis = metrics_without_rbis.fetch("types.sig.count", 0)
66
- snapshot.methods_without_sig_excluding_rbis = metrics_without_rbis.fetch("types.input.methods.total",
67
- 0) - snapshot.methods_with_sig_excluding_rbis
57
+ snapshot.methods_without_sig_excluding_rbis = metrics_without_rbis.fetch(
58
+ "types.input.methods.total",
59
+ 0,
60
+ ) - snapshot.methods_with_sig_excluding_rbis
68
61
  end
69
62
 
70
63
  Snapshot::STRICTNESSES.each do |strictness|
@@ -77,40 +70,34 @@ module Spoom
77
70
  end
78
71
  end
79
72
 
80
- snapshot.version_static = Spoom::Sorbet.version_from_gemfile_lock(gem: "sorbet-static", path: path)
81
- snapshot.version_runtime = Spoom::Sorbet.version_from_gemfile_lock(gem: "sorbet-runtime", path: path)
73
+ snapshot.version_static = context.gem_version_from_gemfile_lock("sorbet-static")
74
+ snapshot.version_runtime = context.gem_version_from_gemfile_lock("sorbet-runtime")
82
75
 
83
- files = Spoom::Sorbet.srb_files(new_config, path: path)
76
+ files = context.srb_files(with_config: new_config)
84
77
  snapshot.rbi_files = files.count { |file| file.end_with?(".rbi") }
85
78
 
86
79
  snapshot
87
80
  end
88
81
 
89
- sig { params(snapshots: T::Array[Snapshot], palette: D3::ColorPalette, path: String).returns(Report) }
90
- def report(snapshots, palette:, path: ".")
91
- intro_commit = Git.sorbet_intro_commit(path: path)
82
+ sig { params(context: Context, snapshots: T::Array[Snapshot], palette: D3::ColorPalette).returns(Report) }
83
+ def report(context, snapshots, palette:)
84
+ intro_commit = context.sorbet_intro_commit
92
85
 
93
86
  Report.new(
94
- project_name: File.basename(File.expand_path(path)),
87
+ project_name: File.basename(context.absolute_path),
95
88
  palette: palette,
96
89
  snapshots: snapshots,
97
- sigils_tree: sigils_tree(path: path),
90
+ sigils_tree: sigils_tree(context),
98
91
  sorbet_intro_commit: intro_commit&.sha,
99
92
  sorbet_intro_date: intro_commit&.time,
100
93
  )
101
94
  end
102
95
 
103
- sig { params(path: String).returns(Sorbet::Config) }
104
- def sorbet_config(path: ".")
105
- Sorbet::Config.parse_file("#{path}/#{Spoom::Sorbet::CONFIG_PATH}")
106
- end
107
-
108
- sig { params(path: String).returns(FileTree) }
109
- def sigils_tree(path: ".")
110
- config = sorbet_config(path: path)
111
- files = Sorbet.srb_files(config, path: path)
96
+ sig { params(context: Context).returns(FileTree) }
97
+ def sigils_tree(context)
98
+ files = context.srb_files
112
99
 
113
- extensions = config.allowed_extensions
100
+ extensions = context.sorbet_config.allowed_extensions
114
101
  extensions = [".rb"] if extensions.empty?
115
102
  extensions -= [".rbi"]
116
103
 
@@ -118,7 +105,7 @@ module Spoom
118
105
  files.select! { |file| file =~ pattern }
119
106
  files.reject! { |file| file =~ %r{/test/} }
120
107
 
121
- FileTree.new(files, strip_prefix: path)
108
+ FileTree.new(files, strip_prefix: context.absolute_path)
122
109
  end
123
110
  end
124
111
  end
@@ -18,13 +18,16 @@ module Spoom
18
18
  class Parser
19
19
  extend T::Sig
20
20
 
21
- HEADER = T.let([
22
- "👋 Hey there! Heads up that this is not a release build of sorbet.",
23
- "Release builds are faster and more well-supported by the Sorbet team.",
24
- "Check out the README to learn how to build Sorbet in release mode.",
25
- "To forcibly silence this error, either pass --silence-dev-message,",
26
- "or set SORBET_SILENCE_DEV_MESSAGE=1 in your shell environment.",
27
- ], T::Array[String])
21
+ HEADER = T.let(
22
+ [
23
+ "👋 Hey there! Heads up that this is not a release build of sorbet.",
24
+ "Release builds are faster and more well-supported by the Sorbet team.",
25
+ "Check out the README to learn how to build Sorbet in release mode.",
26
+ "To forcibly silence this error, either pass --silence-dev-message,",
27
+ "or set SORBET_SILENCE_DEV_MESSAGE=1 in your shell environment.",
28
+ ],
29
+ T::Array[String],
30
+ )
28
31
 
29
32
  class << self
30
33
  extend T::Sig