Skip to content

Commit d8f80b4

Browse files
committed
sorbet: upgrade 19 files from typed: true to typed: strict
Upgrades these files from `# typed: true # rubocop:todo Sorbet/StrictSigil` to `# typed: strict`, adds all required type annotations, and resolves all resulting type errors. Files upgraded: - dependable.rb - dependency.rb - dependency_collector.rb - description_cache_store.rb - exceptions.rb - formula_auditor.rb - global.rb - ignorable.rb - manpages/converter/kramdown.rb - manpages/converter/roff.rb - manpages/parser/ronn.rb - requirement.rb - requirements/macos_requirement.rb - resource.rb - resource_auditor.rb - style.rb - tab.rb - tap_auditor.rb - utils/github.rb Also adds typed generics (Key/Value type members) to CacheStoreDatabase and CacheStore, and types the `val` parameter of Tab#with? and Tab#without? as T.any(String, Dependency, Requirement). Resolves #17297
1 parent 410b1fc commit d8f80b4

73 files changed

Lines changed: 1453 additions & 580 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Library/Homebrew/bottle.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def installed_size
194194

195195
sig { returns(Filename) }
196196
def filename
197-
Filename.create(resource.owner, @tag, @spec.rebuild)
197+
Filename.create(T.cast(resource.owner, Formula), @tag, @spec.rebuild)
198198
end
199199

200200
sig { returns(T.nilable(Resource::BottleManifest)) }
@@ -259,7 +259,7 @@ def root_url(val = nil, specs = {})
259259

260260
@root_url = T.let(val, T.nilable(String))
261261

262-
filename = Filename.create(resource.owner, @tag, @spec.rebuild)
262+
filename = Filename.create(T.cast(resource.owner, Formula), @tag, @spec.rebuild)
263263
resource_checksum = resource.checksum
264264
odie "resource checksum is nil" if resource_checksum.nil?
265265

Library/Homebrew/brew.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,16 @@
163163
#{Formatter.bold("Do not report any issues to Homebrew/* repositories!")}
164164
Read the above document instead before opening any issues or PRs.
165165
EOS
166-
elsif e.formula.head? || e.formula.deprecated? || e.formula.disabled?
167-
reason = if e.formula.head?
166+
elsif (formula = e.formula) && (formula.head? || formula.deprecated? || formula.disabled?)
167+
reason = if formula.head?
168168
"was built from an unstable upstream --HEAD"
169-
elsif e.formula.deprecated?
169+
elsif formula.deprecated?
170170
"is deprecated"
171-
elsif e.formula.disabled?
171+
elsif formula.disabled?
172172
"is disabled"
173173
end
174174
$stderr.puts <<~EOS
175-
#{e.formula.name}'s formula #{reason}.
175+
#{formula.name}'s formula #{reason}.
176176
This build failure is expected behaviour.
177177
EOS
178178
end

Library/Homebrew/build.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ def expand_reqs
6969
sig { returns(T::Array[Dependency]) }
7070
def expand_deps
7171
formula.recursive_dependencies do |dependent, dep|
72-
build = effective_build_options_for(dependent)
72+
build = effective_build_options_for(T.cast(dependent, Formula))
7373
if dep.prune_from_option?(build) ||
74-
dep.prune_if_build_and_not_dependent?(dependent, formula) ||
74+
dep.prune_if_build_and_not_dependent?(T.cast(dependent, Formula), formula) ||
7575
(dep.test? && !dep.build?) || dep.implicit?
7676
Dependency.prune
7777
elsif dep.build?

Library/Homebrew/build_options.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def initialize(args, options)
3030
# args << "--with-example1"
3131
# end
3232
# ```
33-
sig { params(val: T.any(String, Requirement, Dependency)).returns(T::Boolean) }
33+
sig { params(val: T.any(String, Dependable)).returns(T::Boolean) }
3434
def with?(val)
3535
option_names = if val.is_a?(String)
3636
[val]
@@ -56,7 +56,7 @@ def with?(val)
5656
# ```ruby
5757
# args << "--no-spam-plz" if build.without? "spam"
5858
# ```
59-
sig { params(val: T.any(String, Requirement, Dependency)).returns(T::Boolean) }
59+
sig { params(val: T.any(String, Dependable)).returns(T::Boolean) }
6060
def without?(val)
6161
!with?(val)
6262
end

Library/Homebrew/bundle.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ def mark_as_installed_on_request!(entries)
140140
next if installed_formulae.exclude?(name)
141141

142142
tab = Tab.for_name(name)
143-
next if tab.tabfile.blank? || !tab.tabfile.exist?
143+
tabfile = tab.tabfile
144+
next if tabfile.blank? || !tabfile.exist?
144145
next if tab.installed_on_request
145146

146147
next name if use_brew_tab

Library/Homebrew/bundle/brew.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,7 @@ def formula_to_hash(formula)
287287
installed_as_dependency = tab.installed_as_dependency
288288
installed_on_request = tab.installed_on_request
289289
runtime_dependencies = if (runtime_deps = tab.runtime_dependencies)
290-
runtime_deps.filter_map { |d| d["full_name"] }
291-
290+
T.cast(runtime_deps, T::Array[T::Hash[String, T.untyped]]).filter_map { |d| d["full_name"] }
292291
end
293292
poured_from_bottle = tab.poured_from_bottle
294293
end

Library/Homebrew/cache_store.rb

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,20 @@
88
# residing in the `HOMEBREW_CACHE`.
99
#
1010
class CacheStoreDatabase
11+
extend T::Generic
12+
13+
# Sorbet type members are mutable by design and cannot be frozen.
14+
Key = type_member # rubocop:disable Style/MutableConstant
15+
# Sorbet type members are mutable by design and cannot be frozen.
16+
Value = type_member # rubocop:disable Style/MutableConstant
17+
1118
# Yields the cache store database.
1219
# Closes the database after use if it has been loaded.
13-
#
14-
# @param [Symbol] type
15-
# @yield [CacheStoreDatabase] self
1620
sig {
1721
type_parameters(:U)
1822
.params(
1923
type: Symbol,
20-
_blk: T.proc.params(arg0: CacheStoreDatabase).returns(T.type_parameter(:U)),
24+
_blk: T.proc.params(arg0: CacheStoreDatabase[T.anything, T.anything]).returns(T.type_parameter(:U)),
2125
)
2226
.returns(T.type_parameter(:U))
2327
}
@@ -47,32 +51,29 @@ def self.use(type, &_blk)
4751
end
4852

4953
# Creates a CacheStoreDatabase.
50-
#
51-
# @param [Symbol] type
52-
# @return [nil]
5354
sig { params(type: Symbol).void }
5455
def initialize(type)
5556
@type = type
5657
@dirty = T.let(false, T.nilable(T::Boolean))
5758
end
5859

5960
# Sets a value in the underlying database (and creates it if necessary).
60-
sig { params(key: T.anything, value: T.anything).void }
61+
sig { params(key: Key, value: Value).void }
6162
def set(key, value)
6263
dirty!
6364
db[key] = value
6465
end
6566

6667
# Gets a value from the underlying database (if it already exists).
67-
sig { params(key: T.anything).returns(T.untyped) }
68+
sig { params(key: Key).returns(T.nilable(Value)) }
6869
def get(key)
6970
return unless created?
7071

7172
db[key]
7273
end
7374

7475
# Deletes a value from the underlying database (if it already exists).
75-
sig { params(key: T.anything).void }
76+
sig { params(key: Key).void }
7677
def delete(key)
7778
return unless created?
7879

@@ -99,16 +100,12 @@ def write_if_dirty!
99100
end
100101

101102
# Returns `true` if the cache file has been created for the given `@type`.
102-
#
103-
# @return [Boolean]
104103
sig { returns(T::Boolean) }
105104
def created?
106105
cache_path.exist?
107106
end
108107

109108
# Returns the modification time of the cache file (if it already exists).
110-
#
111-
# @return [Time]
112109
sig { returns(T.nilable(Time)) }
113110
def mtime
114111
return unless created?
@@ -117,25 +114,23 @@ def mtime
117114
end
118115

119116
# Performs a `select` on the underlying database.
120-
#
121-
# @return [Hash]
122-
sig { params(block: T.proc.params(arg0: T.untyped, arg1: T.untyped).returns(BasicObject)).returns(T::Hash[T.untyped, T.untyped]) }
117+
sig {
118+
overridable.params(block: T.proc.params(arg0: Key, arg1: Value).returns(BasicObject)).returns(T::Hash[Key, Value])
119+
}
123120
def select(&block)
124121
db.select(&block)
125122
end
126123

127124
# Returns `true` if the cache is empty.
128-
#
129-
# @return [Boolean]
130125
sig { returns(T::Boolean) }
131126
def empty?
132127
db.empty?
133128
end
134129

135130
# Performs a `each_key` on the underlying database.
136-
#
137-
# @return [Hash]
138-
sig { params(block: T.proc.params(arg0: T.untyped).returns(BasicObject)).returns(T::Hash[T.untyped, T.untyped]) }
131+
sig {
132+
params(block: T.proc.params(arg0: Key).returns(BasicObject)).returns(T::Hash[Key, Value])
133+
}
139134
def each_key(&block)
140135
db.each_key(&block)
141136
end
@@ -145,11 +140,9 @@ def each_key(&block)
145140
# Lazily loaded database in read/write mode. If this method is called, a
146141
# database file will be created in the `HOMEBREW_CACHE` with a name
147142
# corresponding to the `@type` instance variable.
148-
#
149-
# @return [Hash] db
150-
sig { returns(T::Hash[T.untyped, T.untyped]) }
143+
sig { returns(T::Hash[Key, Value]) }
151144
def db
152-
@db ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
145+
@db ||= T.let({}, T.nilable(T::Hash[Key, Value]))
153146
return @db if !@db.empty? || !created?
154147

155148
begin
@@ -163,8 +156,6 @@ def db
163156

164157
# The path where the database resides in the `HOMEBREW_CACHE` for the given
165158
# `@type`.
166-
#
167-
# @return [Pathname]
168159
sig { returns(Pathname) }
169160
def cache_path
170161
HOMEBREW_CACHE/"#{@type}.json"
@@ -177,8 +168,6 @@ def dirty!
177168
end
178169

179170
# Returns `true` if the cache needs to be written to disk.
180-
#
181-
# @return [Boolean]
182171
sig { returns(T::Boolean) }
183172
def dirty?
184173
!!@dirty
@@ -190,20 +179,23 @@ def dirty?
190179
# storage mechanism.
191180
#
192181
class CacheStore # rubocop:todo Style/OneClassPerFile
182+
extend T::Generic
193183
extend T::Helpers
194184

195185
abstract!
196186

197-
# @param [CacheStoreDatabase] database
198-
# @return [nil]
199-
sig { params(database: CacheStoreDatabase).void }
187+
# Sorbet type members are mutable by design and cannot be frozen.
188+
Key = type_member # rubocop:disable Style/MutableConstant
189+
# Sorbet type members are mutable by design and cannot be frozen.
190+
Value = type_member # rubocop:disable Style/MutableConstant
191+
192+
sig { params(database: CacheStoreDatabase[Key, Value]).void }
200193
def initialize(database)
201-
@database = database
194+
@database = T.let(database, CacheStoreDatabase[Key, Value])
202195
end
203196

204197
protected
205198

206-
# @return [CacheStoreDatabase]
207-
sig { returns(CacheStoreDatabase) }
199+
sig { returns(CacheStoreDatabase[Key, Value]) }
208200
attr_reader :database
209201
end

Library/Homebrew/cask/dsl/depends_on.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,11 @@ def macos=(*args)
8181
elsif first_arg.is_a?(Symbol) && MacOSVersion::SYMBOLS.key?(first_arg)
8282
MacOSRequirement.new([args.first], comparator: "==")
8383
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*:(?<version>\S+)\s*$/.match(first_arg_s))
84-
MacOSRequirement.new([T.must(md[:version]).to_sym], comparator: md[:comparator])
84+
# The named capture groups must exist, so we use T.must to assert that they do.
85+
MacOSRequirement.new([T.must(md[:version]).to_sym], comparator: T.must(md[:comparator]))
8586
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*(?<version>\S+)\s*$/.match(first_arg_s))
86-
MacOSRequirement.new([md[:version]], comparator: md[:comparator])
87+
# The named capture groups must exist, so we use T.must to assert that they do.
88+
MacOSRequirement.new([md[:version]], comparator: T.must(md[:comparator]))
8789
# This is not duplicate of the first case: see `args.first` and a different comparator.
8890
else # rubocop:disable Lint/DuplicateBranch
8991
MacOSRequirement.new([args.first], comparator: "==")

Library/Homebrew/cask/tab.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ def self.empty
6868
sig { params(cask: Cask).returns(T::Hash[Symbol, T::Array[T::Hash[String, T.untyped]]]) }
6969
def self.runtime_deps_hash(cask)
7070
cask_and_formula_dep_graph = ::Utils::TopologicalHash.graph_package_dependencies(cask)
71-
cask_deps, formula_deps = cask_and_formula_dep_graph.values.flatten.uniq.partition do |dep|
71+
cask_deps, formula_deps = T.cast(cask_and_formula_dep_graph.values.flatten.uniq.partition do |dep|
7272
dep.is_a?(Cask)
73-
end
73+
end, [T::Array[Cask], T::Array[Formula]])
7474

7575
runtime_deps = {}
7676

@@ -126,7 +126,7 @@ def to_s
126126
elsif loaded_from_api
127127
s << "using the formulae.brew.sh API"
128128
end
129-
s << Time.at(time).strftime("on %Y-%m-%d at %H:%M:%S") if time
129+
s << Time.at(T.must(time)).strftime("on %Y-%m-%d at %H:%M:%S") if time
130130
s.join(" ")
131131
end
132132
end

Library/Homebrew/cask_dependent.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,18 @@ def requirements
8080
)
8181
end
8282

83-
sig { params(block: T.nilable(T.proc.returns(T::Array[Dependency]))).returns(T::Array[Dependency]) }
83+
sig {
84+
params(block: T.nilable(T.proc.params(arg0: T.any(Formula, CaskDependent, SoftwareSpec),
85+
arg1: Dependency).void)).returns(T::Array[Dependency])
86+
}
8487
def recursive_dependencies(&block)
8588
Dependency.expand(self, &block)
8689
end
8790

88-
sig { params(block: T.nilable(T.proc.returns(CaskDependent::Requirement))).returns(Requirements) }
91+
sig {
92+
params(block: T.nilable(T.proc.params(arg0: T.any(Formula, CaskDependent, SoftwareSpec), arg1: ::Requirement)
93+
.returns(CaskDependent::Requirement))).returns(Requirements)
94+
}
8995
def recursive_requirements(&block)
9096
Requirement.expand(self, &block)
9197
end

0 commit comments

Comments
 (0)