Skip to content

Commit ca8e0ef

Browse files
committed
cask/artifact: enable Sorbet typed: strict
Enable strict typing for the abstract base classes in `Cask::Artifact`: - `AbstractArtifact` - `AbstractFlightBlock` - `AbstractUninstall` - `Relocated` This adds proper type signatures to all methods and updates the typing level from `typed: true` to `typed: strict`. Also marks `english_name` and `dirmethod` as `overridable` in `AbstractArtifact` and adds `override` to subclasses that override them. Advances #17297
1 parent 2a48e23 commit ca8e0ef

23 files changed

+215
-102
lines changed

Library/Homebrew/bundle.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def which_formula?(name)
101101
which(name).present?
102102
end
103103

104-
sig { params(block: T.proc.returns(T.anything)).returns(T.untyped) }
104+
sig { type_parameters(:U).params(block: T.proc.returns(T.type_parameter(:U))).returns(T.type_parameter(:U)) }
105105
def exchange_uid_if_needed!(&block)
106106
euid = Process.euid
107107
uid = Process.uid

Library/Homebrew/cache_store.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ class CacheStoreDatabase
2222
.returns(T.type_parameter(:U))
2323
}
2424
def self.use(type, &_blk)
25-
@db_type_reference_hash ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
26-
@db_type_reference_hash[type] ||= {}
27-
type_ref = @db_type_reference_hash[type]
25+
@db_type_reference_hash ||= T.let({}, T.nilable(T::Hash[Symbol, { count: Integer, db: CacheStoreDatabase }]))
26+
@db_type_reference_hash[type] ||= { count: 0, db: CacheStoreDatabase.new(type) }
27+
type_ref = @db_type_reference_hash.fetch(type)
2828

2929
type_ref[:count] ||= 0
3030
type_ref[:count] += 1

Library/Homebrew/cask/artifact/app.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Artifact
88
# Artifact corresponding to the `app` stanza.
99
class App < Moved
1010
sig {
11-
params(
11+
override.params(
1212
adopt: T::Boolean,
1313
auto_updates: T.nilable(T::Boolean),
1414
force: T::Boolean,

Library/Homebrew/cask/artifact/artifact.rb

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@ def self.english_name
1212
"Generic Artifact"
1313
end
1414

15-
sig { params(cask: Cask, args: T.untyped).returns(T.attached_class) }
16-
def self.from_args(cask, *args)
17-
source, options = args
18-
15+
sig { params(cask: Cask, source: T.nilable(String), target_hash: T.anything).returns(Relocated) }
16+
def self.from_args(cask, source = nil, **target_hash)
1917
raise CaskInvalidError.new(cask.token, "No source provided for #{english_name}.") if source.blank?
2018

21-
unless options&.key?(:target)
19+
unless target_hash.key?(:target)
2220
raise CaskInvalidError.new(cask.token, "#{english_name} '#{source}' requires a target.")
2321
end
2422

25-
new(cask, source, **options)
23+
new(cask, source, **target_hash)
2624
end
2725

28-
sig { params(target: T.any(String, Pathname)).returns(Pathname) }
26+
# FIXME: This is a pre-existing violation
27+
# rubocop:disable Sorbet/AllowIncompatibleOverride
28+
sig { override(allow_incompatible: true).params(target: T.any(String, Pathname)).returns(Pathname) }
29+
# rubocop:enable Sorbet/AllowIncompatibleOverride
2930
def resolve_target(target)
3031
super(target, base_dir: nil)
3132
end

Library/Homebrew/cask/artifact/bashcompletion.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ module Cask
77
module Artifact
88
# Artifact corresponding to the `bash_completion` stanza.
99
class BashCompletion < ShellCompletion
10-
sig { params(target: T.any(String, Pathname)).returns(Pathname) }
10+
# FIXME: This is a pre-existing violation
11+
# rubocop:disable Sorbet/AllowIncompatibleOverride
12+
sig { override(allow_incompatible: true).params(target: T.any(String, Pathname)).returns(Pathname) }
13+
# rubocop:enable Sorbet/AllowIncompatibleOverride
1114
def resolve_target(target)
1215
name = if File.extname(target).nil?
1316
target

Library/Homebrew/cask/artifact/binary.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# typed: true # rubocop:todo Sorbet/StrictSigil
1+
# typed: strict
22
# frozen_string_literal: true
33

44
require "cask/artifact/symlinked"
@@ -7,7 +7,8 @@ module Cask
77
module Artifact
88
# Artifact corresponding to the `binary` stanza.
99
class Binary < Symlinked
10-
def link(command: nil, **options)
10+
sig { override.params(command: T.class_of(SystemCommand), force: T::Boolean, adopt: T::Boolean, _options: T.anything).void }
11+
def link(command:, force: false, adopt: false, **_options)
1112
super
1213
return if source.executable?
1314

Library/Homebrew/cask/artifact/fishcompletion.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ module Cask
77
module Artifact
88
# Artifact corresponding to the `fish_completion` stanza.
99
class FishCompletion < ShellCompletion
10-
sig { params(target: T.any(String, Pathname)).returns(Pathname) }
10+
# FIXME: This is a pre-existing violation
11+
# rubocop:disable Sorbet/AllowIncompatibleOverride
12+
sig { override(allow_incompatible: true).params(target: T.any(String, Pathname)).returns(Pathname) }
13+
# rubocop:enable Sorbet/AllowIncompatibleOverride
1114
def resolve_target(target)
1215
name = if target.to_s.end_with? ".fish"
1316
target

Library/Homebrew/cask/artifact/installer.rb

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# typed: true # rubocop:todo Sorbet/StrictSigil
1+
# typed: strict
22
# frozen_string_literal: true
33

44
require "cask/artifact/abstract_artifact"
@@ -8,12 +8,13 @@ module Cask
88
module Artifact
99
# Artifact corresponding to the `installer` stanza.
1010
class Installer < AbstractArtifact
11-
VALID_KEYS = Set.new([
12-
:manual,
13-
:script,
14-
]).freeze
11+
VALID_KEYS = T.let(
12+
Set.new([:manual, :script]).freeze,
13+
T::Set[Symbol],
14+
)
1515

16-
def install_phase(command: nil, **_)
16+
sig { params(command: T.class_of(SystemCommand), _options: T.anything).void }
17+
def install_phase(command:, **_options)
1718
if manual_install
1819
puts <<~EOS
1920
Cask #{cask} only provides a manual installer. To run it and complete the installation:
@@ -35,6 +36,7 @@ def install_phase(command: nil, **_)
3536
end
3637
end
3738

39+
sig { params(cask: Cask, args: DirectivesType).returns(Installer) }
3840
def self.from_args(cask, **args)
3941
raise CaskInvalidError.new(cask, "'installer' stanza requires an argument.") if args.empty?
4042

@@ -59,18 +61,23 @@ def self.from_args(cask, **args)
5961
new(cask, **args)
6062
end
6163

62-
attr_reader :path, :args
64+
sig { returns(Pathname) }
65+
attr_reader :path
66+
67+
sig { returns(T::Hash[Symbol, DirectivesType]) }
68+
attr_reader :args
6369

6470
sig { returns(T::Boolean) }
6571
attr_reader :manual_install
6672

73+
sig { params(cask: Cask, args: DirectivesType).void }
6774
def initialize(cask, **args)
6875
super
6976

70-
if args.key?(:manual)
71-
@path = Pathname(args[:manual])
72-
@args = []
73-
@manual_install = true
77+
if (manual = T.cast(args[:manual], T.nilable(String)))
78+
@path = T.let(Pathname(manual), Pathname)
79+
@args = T.let({}, T::Hash[Symbol, DirectivesType])
80+
@manual_install = T.let(true, T::Boolean)
7481
else
7582
path, @args = self.class.read_script_arguments(
7683
args[:script], self.class.dsl_key.to_s, { must_succeed: true, sudo: false }, print_stdout: true
@@ -85,10 +92,9 @@ def initialize(cask, **args)
8592
sig { override.returns(String) }
8693
def summarize = path.to_s
8794

95+
sig { returns(T::Hash[Symbol, T.anything]) }
8896
def to_h
89-
{ path: }.tap do |h|
90-
h[:args] = args unless manual_install
91-
end
97+
manual_install ? { path: } : { path:, args: }
9298
end
9399
end
94100
end

Library/Homebrew/cask/artifact/keyboard_layout.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# typed: true # rubocop:todo Sorbet/StrictSigil
1+
# typed: strict
22
# frozen_string_literal: true
33

44
require "cask/artifact/moved"
@@ -7,19 +7,22 @@ module Cask
77
module Artifact
88
# Artifact corresponding to the `keyboard_layout` stanza.
99
class KeyboardLayout < Moved
10-
def install_phase(**options)
10+
sig { override.params(command: T.class_of(SystemCommand), options: T.anything).void }
11+
def install_phase(command:, **options)
1112
super
1213
delete_keyboard_layout_cache(**options)
1314
end
1415

15-
def uninstall_phase(**options)
16+
sig { override.params(command: T.class_of(SystemCommand), options: T.anything).void }
17+
def uninstall_phase(command:, **options)
1618
super
1719
delete_keyboard_layout_cache(**options)
1820
end
1921

2022
private
2123

22-
def delete_keyboard_layout_cache(command: nil, **_)
24+
sig { params(command: T.class_of(SystemCommand), _options: T.anything).void }
25+
def delete_keyboard_layout_cache(command:, **_options)
2326
command.run!(
2427
"/bin/rm",
2528
args: ["-f", "--", "/System/Library/Caches/com.apple.IntlDataCache.le*"],

Library/Homebrew/cask/artifact/manpage.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# typed: true # rubocop:todo Sorbet/StrictSigil
1+
# typed: strict
22
# frozen_string_literal: true
33

44
require "cask/artifact/symlinked"
@@ -7,22 +7,29 @@ module Cask
77
module Artifact
88
# Artifact corresponding to the `manpage` stanza.
99
class Manpage < Symlinked
10+
sig { returns(String) }
1011
attr_reader :section
1112

12-
def self.from_args(cask, source)
13+
sig { params(cask: Cask, source: String, _target_hash: T.anything).returns(Manpage) }
14+
def self.from_args(cask, source, **_target_hash)
1315
section = source.to_s[/\.([1-8]|n|l)(?:\.gz)?$/, 1]
1416

1517
raise CaskInvalidError, "'#{source}' is not a valid man page name" unless section
1618

17-
new(cask, source, section)
19+
new(cask, T.must(source), section)
1820
end
1921

22+
sig { params(cask: Cask, source: String, section: String).void }
2023
def initialize(cask, source, section)
2124
@section = section
2225

2326
super(cask, source)
2427
end
2528

29+
# FIXME: This is a pre-existing violation
30+
# rubocop:disable Sorbet/AllowIncompatibleOverride
31+
sig { override(allow_incompatible: true).params(target: T.any(String, Pathname)).returns(Pathname) }
32+
# rubocop:enable Sorbet/AllowIncompatibleOverride
2633
def resolve_target(target)
2734
config.manpagedir.join("man#{section}", target)
2835
end

0 commit comments

Comments
 (0)