diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index 3c6e03b77a..a35001a936 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -70,6 +70,11 @@ Style/Documentation: - version.rb - tap.rb +Homebrew/NegateInclude: + Exclude: + # YARD runs stand-alone. + - yard/docstring_parser.rb + Style/DocumentationMethod: Include: - "formula.rb" diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index d8c898284f..a01e6a7da9 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -18,6 +18,7 @@ end group :doc, optional: true do gem "yard", require: false gem "yard-sorbet", require: false + gem "redcarpet", require: false end group :ast, optional: true do gem "rubocop-ast", require: false diff --git a/Library/Homebrew/PATH.rb b/Library/Homebrew/PATH.rb index 474bd2f0c1..577bdc8ab9 100644 --- a/Library/Homebrew/PATH.rb +++ b/Library/Homebrew/PATH.rb @@ -60,7 +60,6 @@ class PATH @paths.join(File::PATH_SEPARATOR) end - # @!visibility private sig { returns(String) } def to_s = to_str diff --git a/Library/Homebrew/attestation.rb b/Library/Homebrew/attestation.rb index 2dc57ad57a..9f40bf1fe9 100644 --- a/Library/Homebrew/attestation.rb +++ b/Library/Homebrew/attestation.rb @@ -39,8 +39,8 @@ module Homebrew sig { returns(Pathname) } def self.gh_executable # NOTE: We disable HOMEBREW_VERIFY_ATTESTATIONS when installing `gh` itself, - # to prevent a cycle during bootstrapping. This can eventually be resolved - # by vendoring a pure-Ruby Sigstore verifier client. + # to prevent a cycle during bootstrapping. This can eventually be resolved + # by vendoring a pure-Ruby Sigstore verifier client. @gh_executable ||= T.let(with_env("HOMEBREW_VERIFY_ATTESTATIONS" => nil) do ensure_executable!("gh") end, T.nilable(Pathname)) diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 3ff4e3e928..e2303765d3 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -265,7 +265,7 @@ EOS fi } -# NOTE: the members of the array in the second arg must not have spaces! +# NOTE: The members of the array in the second arg must not have spaces! check-array-membership() { local item=$1 shift diff --git a/Library/Homebrew/brew_irbrc b/Library/Homebrew/brew_irbrc index b31faa3525..00217d3fdd 100644 --- a/Library/Homebrew/brew_irbrc +++ b/Library/Homebrew/brew_irbrc @@ -1,6 +1,6 @@ -# Note: that we use a non-standard config file name to reduce -# name clashes with other IRB config files like `.irbrc`. -# Note #2: This doesn't work with system Ruby for some reason. +# NOTE: We use a non-standard config file name to reduce name clashes with +# other IRB config files like `.irbrc`. +# NOTE: This doesn't work with system Ruby for some reason. require 'irb/completion' diff --git a/Library/Homebrew/build_options.rb b/Library/Homebrew/build_options.rb index 75f39c3193..ccc3117386 100644 --- a/Library/Homebrew/build_options.rb +++ b/Library/Homebrew/build_options.rb @@ -9,16 +9,26 @@ class BuildOptions end # True if a {Formula} is being built with a specific option. - #
args << "--i-want-spam" if build.with? "spam"
   #
+  # ### Examples
+  #
+  # ```ruby
+  # args << "--i-want-spam" if build.with? "spam"
+  # ```
+  #
+  # ```ruby
   # args << "--qt-gui" if build.with? "qt" # "--with-qt" ==> build.with? "qt"
+  # ```
   #
-  # # If a formula presents a user with a choice, but the choice must be fulfilled:
+  # If a formula presents a user with a choice, but the choice must be fulfilled:
+  #
+  # ```ruby
   # if build.with? "example2"
   #   args << "--with-example2"
   # else
   #   args << "--with-example1"
-  # end
+ # end + # ``` def with?(val) option_names = val.respond_to?(:option_names) ? val.option_names : [val] @@ -34,7 +44,12 @@ class BuildOptions end # True if a {Formula} is being built without a specific option. - #
args << "--no-spam-plz" if build.without? "spam"
+ # + # ### Example + # + # ```ruby + # args << "--no-spam-plz" if build.without? "spam" + # ``` def without?(val) !with?(val) end @@ -45,19 +60,33 @@ class BuildOptions end # True if a {Formula} is being built with {Formula.head} instead of {Formula.stable}. - #
args << "--some-new-stuff" if build.head?
- #
# If there are multiple conditional arguments use a block instead of lines.
+  #
+  # ### Examples
+  #
+  # ```ruby
+  # args << "--some-new-stuff" if build.head?
+  # ```
+  #
+  # If there are multiple conditional arguments use a block instead of lines.
+  #
+  # ```ruby
   # if build.head?
   #   args << "--i-want-pizza"
   #   args << "--and-a-cold-beer" if build.with? "cold-beer"
-  # end
+ # end + # ``` def head? include? "HEAD" end # True if a {Formula} is being built with {Formula.stable} instead of {Formula.head}. # This is the default. - #
args << "--some-beta" if build.head?
+ # + # ### Example + # + # ```ruby + # args << "--some-beta" if build.head? + # ``` def stable? !head? end diff --git a/Library/Homebrew/cask/artifact/abstract_artifact.rb b/Library/Homebrew/cask/artifact/abstract_artifact.rb index a202cad6b4..e722d0bc0f 100644 --- a/Library/Homebrew/cask/artifact/abstract_artifact.rb +++ b/Library/Homebrew/cask/artifact/abstract_artifact.rb @@ -147,7 +147,6 @@ module Cask cask.config end - # @!visibility private sig { returns(String) } def to_s "#{summarize} (#{self.class.english_name})" diff --git a/Library/Homebrew/cask/cask.rb b/Library/Homebrew/cask/cask.rb index e7856806ce..5ffd9fb797 100644 --- a/Library/Homebrew/cask/cask.rb +++ b/Library/Homebrew/cask/cask.rb @@ -78,7 +78,8 @@ module Cask @allow_reassignment = allow_reassignment @loaded_from_api = loaded_from_api @loader = loader - # Sorbet has trouble with bound procs assigned to ivars: https://github.com/sorbet/sorbet/issues/6843 + # Sorbet has trouble with bound procs assigned to instance variables: + # https://github.com/sorbet/sorbet/issues/6843 instance_variable_set(:@block, block) @default_config = config || Config.new @@ -323,11 +324,9 @@ module Cask end # @api public - # @!visibility private sig { returns(String) } def to_s = token - # @!visibility private sig { returns(String) } def inspect "#" diff --git a/Library/Homebrew/cask/dsl.rb b/Library/Homebrew/cask/dsl.rb index 24424f3f70..62dee57438 100644 --- a/Library/Homebrew/cask/dsl.rb +++ b/Library/Homebrew/cask/dsl.rb @@ -112,6 +112,16 @@ module Cask @token = cask.token end + # Specifies the cask's name. + # + # NOTE: Multiple names can be specified. + # + # ### Example + # + # ```ruby + # name "Visual Studio Code" + # ``` + # # @api public def name(*args) @name ||= [] @@ -120,6 +130,14 @@ module Cask @name.concat(args.flatten) end + # Describes the cask. + # + # ### Example + # + # ```ruby + # desc "Open-source code editor" + # ``` + # # @api public def desc(description = nil) set_unique_stanza(:desc, description.nil?) { description } @@ -146,6 +164,14 @@ module Cask raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}") end + # Sets the cask's homepage. + # + # ### Example + # + # ```ruby + # homepage "https://code.visualstudio.com/" + # ``` + # # @api public def homepage(homepage = nil) set_unique_stanza(:homepage, homepage.nil?) { homepage } @@ -201,6 +227,14 @@ module Cask @language_blocks.keys.flatten end + # Sets the cask's download URL. + # + # ### Example + # + # ```ruby + # url "https://update.code.visualstudio.com/#{version}/#{arch}/stable" + # ``` + # # @api public def url(*args, **options, &block) caller_location = T.must(caller_locations).fetch(0) @@ -214,6 +248,8 @@ module Cask end end + # Sets the cask's appcast URL. + # # @api public def appcast(*args, **kwargs) set_unique_stanza(:appcast, args.empty? && kwargs.empty?) do @@ -222,6 +258,22 @@ module Cask end end + # Sets the cask's container type or nested container path. + # + # ### Examples + # + # The container is a nested disk image: + # + # ```ruby + # container nested: "orca-#{version}.dmg" + # ``` + # + # The container should not be unarchived: + # + # ```ruby + # container type: :naked + # ``` + # # @api public def container(**kwargs) set_unique_stanza(:container, kwargs.empty?) do @@ -229,6 +281,15 @@ module Cask end end + # Sets the cask's version. + # + # ### Example + # + # ```ruby + # version "1.88.1" + # ``` + # + # @see DSL::Version # @api public def version(arg = nil) set_unique_stanza(:version, arg.nil?) do @@ -240,6 +301,23 @@ module Cask end end + # Sets the cask's download checksum. + # + # ### Example + # + # For universal or single-architecture downloads: + # + # ```ruby + # sha256 "7bdb497080ffafdfd8cc94d8c62b004af1be9599e865e5555e456e2681e150ca" + # ``` + # + # For architecture-dependent downloads: + # + # ```ruby + # sha256 arm: "7bdb497080ffafdfd8cc94d8c62b004af1be9599e865e5555e456e2681e150ca", + # intel: "b3c1c2442480a0219b9e05cf91d03385858c20f04b764ec08a3fa83d1b27e7b2" + # ``` + # # @api public def sha256(arg = nil, arm: nil, intel: nil) should_return = arg.nil? && arm.nil? && intel.nil? @@ -259,6 +337,14 @@ module Cask end end + # Sets the cask's architecture strings. + # + # ### Example + # + # ```ruby + # arch arm: "darwin-arm64", intel: "darwin" + # ``` + # # @api public def arch(arm: nil, intel: nil) should_return = arm.nil? && intel.nil? @@ -270,7 +356,10 @@ module Cask end end - # `depends_on` uses a load method so that multiple stanzas can be merged. + # Declare dependencies and requirements for a cask. + # + # NOTE: Multiple dependencies can be specified. + # # @api public def depends_on(**kwargs) @depends_on ||= DSL::DependsOn.new @@ -284,9 +373,11 @@ module Cask @depends_on end + # Declare conflicts that keep a cask from installing or working correctly. + # # @api public def conflicts_with(**kwargs) - # TODO: remove this constraint, and instead merge multiple conflicts_with stanzas + # TODO: Remove this constraint and instead merge multiple `conflicts_with` stanzas set_unique_stanza(:conflicts_with, kwargs.empty?) { DSL::ConflictsWith.new(**kwargs) } end @@ -298,6 +389,8 @@ module Cask cask.caskroom_path end + # The staged location for this cask, including version number. + # # @api public def staged_path return @staged_path if @staged_path @@ -306,6 +399,8 @@ module Cask @staged_path = caskroom_path.join(cask_version.to_s) end + # Provide the user with cask-specific information at install time. + # # @api public def caveats(*strings, &block) @caveats ||= DSL::Caveats.new(cask) @@ -326,11 +421,15 @@ module Cask @caveats&.discontinued? == true end + # Asserts that the cask artifacts auto-update. + # # @api public def auto_updates(auto_updates = nil) set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates } end + # Automatically fetch the latest version of a cask from changelogs. + # # @api public def livecheck(&block) @livecheck ||= Livecheck.new(cask) @@ -344,6 +443,10 @@ module Cask @livecheck.instance_eval(&block) end + # Declare that a cask is no longer functional or supported. + # + # NOTE: A warning will be shown when trying to install this cask. + # # @api public def deprecate!(date:, because:) @deprecation_date = Date.parse(date) @@ -353,6 +456,10 @@ module Cask @deprecated = true end + # Declare that a cask is no longer functional or supported. + # + # NOTE: An error will be thrown when trying to install this cask. + # # @api public def disable!(date:, because:) @disable_date = Date.parse(date) @@ -405,6 +512,8 @@ module Cask true end + # The directory `app`s are installed into. + # # @api public def appdir return HOMEBREW_CASK_APPDIR_PLACEHOLDER if Cask.generating_hash? diff --git a/Library/Homebrew/cask/dsl/caveats.rb b/Library/Homebrew/cask/dsl/caveats.rb index 2ccb4396be..53b029e75e 100644 --- a/Library/Homebrew/cask/dsl/caveats.rb +++ b/Library/Homebrew/cask/dsl/caveats.rb @@ -37,7 +37,6 @@ module Cask private_class_method :caveat - # @!visibility private sig { returns(String) } def to_s (@custom_caveats + @built_in_caveats.values).join("\n") diff --git a/Library/Homebrew/cask/dsl/container.rb b/Library/Homebrew/cask/dsl/container.rb index bb4beaa27f..54bc3bc4e8 100644 --- a/Library/Homebrew/cask/dsl/container.rb +++ b/Library/Homebrew/cask/dsl/container.rb @@ -27,7 +27,6 @@ module Cask pairs.to_yaml end - # @!visibility private sig { returns(String) } def to_s = pairs.inspect end diff --git a/Library/Homebrew/cask/dsl/postflight.rb b/Library/Homebrew/cask/dsl/postflight.rb index 3ceabd9cab..0747ff8def 100644 --- a/Library/Homebrew/cask/dsl/postflight.rb +++ b/Library/Homebrew/cask/dsl/postflight.rb @@ -9,8 +9,8 @@ module Cask class Postflight < Base include Staged - def suppress_move_to_applications(_options = {}) - odisabled "Cask::DSL#suppress_move_to_applications" + def suppress_move_to_applications(**_options) + odisabled "`Cask::DSL::Postflight#suppress_move_to_applications`" end end end diff --git a/Library/Homebrew/cask/dsl/version.rb b/Library/Homebrew/cask/dsl/version.rb index 853a4f191c..30f8ebcd64 100644 --- a/Library/Homebrew/cask/dsl/version.rb +++ b/Library/Homebrew/cask/dsl/version.rb @@ -94,70 +94,94 @@ module Cask to_s == "latest" end + # The major version. + # # @api public sig { returns(T.self_type) } def major version { slice(MAJOR_MINOR_PATCH_REGEX, 1) } end + # The minor version. + # # @api public sig { returns(T.self_type) } def minor version { slice(MAJOR_MINOR_PATCH_REGEX, 2) } end + # The patch version. + # # @api public sig { returns(T.self_type) } def patch version { slice(MAJOR_MINOR_PATCH_REGEX, 3) } end + # The major and minor version. + # # @api public sig { returns(T.self_type) } def major_minor version { [major, minor].reject(&:empty?).join(".") } end + # The major, minor and patch version. + # # @api public sig { returns(T.self_type) } def major_minor_patch version { [major, minor, patch].reject(&:empty?).join(".") } end + # The minor and patch version. + # # @api public sig { returns(T.self_type) } def minor_patch version { [minor, patch].reject(&:empty?).join(".") } end + # The comma separated values of the version as array. + # # @api public sig { returns(T::Array[Version]) } # Only top-level T.self_type is supported https://sorbet.org/docs/self-type def csv split(",").map { self.class.new(_1) } end + # The version part before the first comma. + # # @api public sig { returns(T.self_type) } def before_comma version { split(",", 2).first } end + # The version part after the first comma. + # # @api public sig { returns(T.self_type) } def after_comma version { split(",", 2).second } end + # The version without any dividers. + # + # @see DIVIDER_REGEX # @api public sig { returns(T.self_type) } def no_dividers version { gsub(DIVIDER_REGEX, "") } end + # The version with the given record separator removed from the end. + # + # @see String#chomp # @api public - sig { params(separator: T.nilable(String)).returns(T.self_type) } - def chomp(separator = nil) - version { to_s.chomp(T.unsafe(separator)) } + sig { params(separator: String).returns(T.self_type) } + def chomp(separator = T.unsafe(nil)) + version { to_s.chomp(separator) } end private diff --git a/Library/Homebrew/cask/exceptions.rb b/Library/Homebrew/cask/exceptions.rb index fc354f4e19..aa4e91863d 100644 --- a/Library/Homebrew/cask/exceptions.rb +++ b/Library/Homebrew/cask/exceptions.rb @@ -13,7 +13,6 @@ module Cask @errors = errors end - # @!visibility private sig { returns(String) } def to_s <<~EOS @@ -41,7 +40,6 @@ module Cask # Error when a cask is not installed. class CaskNotInstalledError < AbstractCaskErrorWithToken - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' is not installed." @@ -57,7 +55,6 @@ module Cask @message = message end - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' has been #{message}" @@ -73,7 +70,6 @@ module Cask @conflicting_cask = conflicting_cask end - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' conflicts with '#{conflicting_cask}'." @@ -82,7 +78,6 @@ module Cask # Error when a cask is not available. class CaskUnavailableError < AbstractCaskErrorWithToken - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' is unavailable#{reason.empty? ? "." : ": #{reason}"}" @@ -91,7 +86,6 @@ module Cask # Error when a cask is unreadable. class CaskUnreadableError < CaskUnavailableError - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' is unreadable#{reason.empty? ? "." : ": #{reason}"}" @@ -107,7 +101,6 @@ module Cask @tap = tap end - # @!visibility private sig { returns(String) } def to_s s = super @@ -142,7 +135,6 @@ module Cask # Error when a cask already exists. class CaskAlreadyCreatedError < AbstractCaskErrorWithToken - # @!visibility private sig { returns(String) } def to_s %Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew edit --cask #{token}")} to edit it.) @@ -151,7 +143,6 @@ module Cask # Error when there is a cyclic cask dependency. class CaskCyclicDependencyError < AbstractCaskErrorWithToken - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' includes cyclic dependencies on other Casks#{reason.empty? ? "." : ": #{reason}"}" @@ -160,7 +151,6 @@ module Cask # Error when a cask depends on itself. class CaskSelfReferencingDependencyError < CaskCyclicDependencyError - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' depends on itself." @@ -169,7 +159,6 @@ module Cask # Error when no cask is specified. class CaskUnspecifiedError < CaskError - # @!visibility private sig { returns(String) } def to_s "This command requires a Cask token." @@ -178,7 +167,6 @@ module Cask # Error when a cask is invalid. class CaskInvalidError < AbstractCaskErrorWithToken - # @!visibility private sig { returns(String) } def to_s "Cask '#{token}' definition is invalid#{reason.empty? ? "." : ": #{reason}"}" @@ -203,7 +191,6 @@ module Cask @reason = reason end - # @!visibility private sig { returns(String) } def to_s s = +"Failed to quarantine #{path}." @@ -220,7 +207,6 @@ module Cask # Error while propagating quarantine information to subdirectories. class CaskQuarantinePropagationError < CaskQuarantineError - # @!visibility private sig { returns(String) } def to_s s = +"Failed to quarantine one or more files within #{path}." @@ -237,7 +223,6 @@ module Cask # Error while removing quarantine information. class CaskQuarantineReleaseError < CaskQuarantineError - # @!visibility private sig { returns(String) } def to_s s = +"Failed to release #{path} from quarantine." diff --git a/Library/Homebrew/cask/url.rb b/Library/Homebrew/cask/url.rb index 4afd746397..ca79267196 100644 --- a/Library/Homebrew/cask/url.rb +++ b/Library/Homebrew/cask/url.rb @@ -17,22 +17,32 @@ module Cask extend Forwardable def_delegators :uri, :path, :scheme, :to_s - # @api public sig { params( uri: T.any(URI::Generic, String), + # @api public verified: T.nilable(String), + # @api public using: T.any(Class, Symbol, NilClass), + # @api public tag: T.nilable(String), + # @api public branch: T.nilable(String), + # @api public revisions: T.nilable(T::Array[String]), + # @api public revision: T.nilable(String), + # @api public trust_cert: T.nilable(T::Boolean), + # @api public cookies: T.nilable(T::Hash[String, String]), referer: T.nilable(T.any(URI::Generic, String)), + # @api public header: T.nilable(T.any(String, T::Array[String])), user_agent: T.nilable(T.any(Symbol, String)), + # @api public data: T.nilable(T::Hash[String, String]), + # @api public only_path: T.nilable(String), ).void } @@ -77,8 +87,19 @@ module Cask end class BlockDSL - # To access URL associated with page contents. + # Allow accessing the URL associated with page contents. module PageWithURL + # Get the URL of the fetched page. + # + # ### Example + # + # ```ruby + # url "https://example.org/download" do |page| + # file = page[/href="([^"]+.dmg)"/, 1] + # URL.join(page.url, file) + # end + # ``` + # # @api public sig { returns(URI::Generic) } attr_accessor :url @@ -87,12 +108,12 @@ module Cask sig { params( uri: T.nilable(T.any(URI::Generic, String)), - dsl: T.nilable(::Cask::DSL), + dsl: ::Cask::DSL, block: T.proc.params(arg0: T.all(String, PageWithURL)) .returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash])), ).void } - def initialize(uri, dsl: nil, &block) + def initialize(uri, dsl:, &block) @uri = uri @dsl = dsl @block = block @@ -114,6 +135,8 @@ module Cask end end + # Allows calling a nested `url` stanza in a `url do` block. + # # @api public sig { params( @@ -123,10 +146,12 @@ module Cask ).returns(T.any(T.any(URI::Generic, String), [T.any(URI::Generic, String), Hash])) } def url(uri, &block) - self.class.new(uri, &block).call + self.class.new(uri, dsl: @dsl, &block).call end private :url + # This allows calling DSL methods from inside a `url` block. + # # @api public def method_missing(method, *args, &block) if @dsl.respond_to?(method) @@ -135,10 +160,12 @@ module Cask super end end + private :method_missing def respond_to_missing?(method, include_all) @dsl.respond_to?(method, include_all) || super end + private :respond_to_missing? end sig { @@ -187,7 +214,7 @@ module Cask super( if block LazyObject.new do - uri2, options = *BlockDSL.new(uri, dsl:, &block).call + uri2, options = *BlockDSL.new(uri, dsl: T.must(dsl), &block).call options ||= {} DSL.new(uri2, **options) end diff --git a/Library/Homebrew/cask/utils.rb b/Library/Homebrew/cask/utils.rb index 8a8cddfbcc..2fe99ae3fa 100644 --- a/Library/Homebrew/cask/utils.rb +++ b/Library/Homebrew/cask/utils.rb @@ -68,9 +68,9 @@ module Cask unless tried_permissions print_stderr = Context.current.debug? || Context.current.verbose? # TODO: Better handling for the case where path is a symlink. - # The -h and -R flags cannot be combined, and behavior is + # The `-h` and `-R` flags cannot be combined and behavior is # dependent on whether the file argument has a trailing - # slash. This should do the right thing, but is fragile. + # slash. This should do the right thing, but is fragile. command.run("/usr/bin/chflags", print_stderr:, args: command_args + ["--", "000", path]) @@ -87,7 +87,7 @@ module Cask unless tried_ownership # in case of ownership problems # TODO: Further examine files to see if ownership is the problem - # before using sudo+chown + # before using `sudo` and `chown`. ohai "Using sudo to gain ownership of path '#{path}'" command.run("/usr/sbin/chown", args: command_args + ["--", User.current, path], diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index f81fc26603..0ab6fbabf9 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -756,7 +756,7 @@ class ReporterHub def dump(auto_update: false) report_all = ENV["HOMEBREW_UPDATE_REPORT_ALL_FORMULAE"].present? if report_all && !Homebrew::EnvConfig.no_install_from_api? - odisabled "HOMEBREW_UPDATE_REPORT_ALL_FORMULAE" + odisabled "`HOMEBREW_UPDATE_REPORT_ALL_FORMULAE`" opoo "This will not report all formulae because Homebrew cannot get this data from the API." report_all = false end diff --git a/Library/Homebrew/compilers.rb b/Library/Homebrew/compilers.rb index 03e8d3e806..62cbfbe29e 100644 --- a/Library/Homebrew/compilers.rb +++ b/Library/Homebrew/compilers.rb @@ -65,7 +65,6 @@ class CompilerFailure type == compiler.type && version_matched end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{type} #{version}>" diff --git a/Library/Homebrew/cxxstdlib.rb b/Library/Homebrew/cxxstdlib.rb index 1745e51c0e..a87523c472 100644 --- a/Library/Homebrew/cxxstdlib.rb +++ b/Library/Homebrew/cxxstdlib.rb @@ -22,7 +22,6 @@ class CxxStdlib type.to_s.gsub(/cxx$/, "c++") end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{compiler} #{type}>" diff --git a/Library/Homebrew/dependencies.rb b/Library/Homebrew/dependencies.rb index a38912a036..6eec3de36e 100644 --- a/Library/Homebrew/dependencies.rb +++ b/Library/Homebrew/dependencies.rb @@ -35,7 +35,6 @@ class Dependencies < SimpleDelegator self.class.new(*__getobj__.reject { |dep| dep.uses_from_macos? && dep.use_macos_install? }) end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{__getobj__}>" @@ -62,7 +61,6 @@ class Requirements < SimpleDelegator self end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: {#{__getobj__.to_a.join(", ")}}>" diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 2e03e08ee3..aff96c1840 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -4,6 +4,8 @@ require "dependable" # A dependency on another Homebrew formula. +# +# @api internal class Dependency extend Forwardable include Dependable @@ -94,11 +96,9 @@ class Dependency false end - # @!visibility private sig { returns(String) } def to_s = name - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{name.inspect} #{tags.inspect}>" @@ -115,6 +115,8 @@ class Dependency # the list. # The default filter, which is applied when a block is not given, omits # optionals and recommends based on what the dependent has asked for + # + # @api internal def expand(dependent, deps = dependent.deps, cache_key: nil, &block) # Keep track dependencies to avoid infinite cyclic dependency recursion. @expand_stack ||= [] @@ -181,6 +183,8 @@ class Dependency end # Keep a dependency, but prune its dependencies. + # + # @api internal sig { void } def keep_but_prune_recursive_deps throw(:action, :keep_but_prune_recursive_deps) @@ -282,7 +286,6 @@ class UsesFromMacOSDependency < Dependency self.class.new(formula.full_name.to_s, tags, bounds:) end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{name.inspect} #{tags.inspect} #{bounds.inspect}>" diff --git a/Library/Homebrew/dev-cmd/extract.rb b/Library/Homebrew/dev-cmd/extract.rb index 3735541c8a..40144dd571 100644 --- a/Library/Homebrew/dev-cmd/extract.rb +++ b/Library/Homebrew/dev-cmd/extract.rb @@ -98,7 +98,7 @@ module Homebrew end odie "Could not find #{name}! The formula or version may not have existed." if test_formula.nil? else - # Search in the root directory of as well as recursively in all of its subdirectories + # Search in the root directory of `repo` as well as recursively in all of its subdirectories. files = Dir[repo/"{,**/}"].filter_map do |dir| Pathname.glob("#{dir}/#{name}.rb").find(&:file?) end diff --git a/Library/Homebrew/dev-cmd/rubydoc.rb b/Library/Homebrew/dev-cmd/rubydoc.rb index 584e298297..e7ca0e9d59 100644 --- a/Library/Homebrew/dev-cmd/rubydoc.rb +++ b/Library/Homebrew/dev-cmd/rubydoc.rb @@ -20,16 +20,18 @@ module Homebrew def run Homebrew.install_bundler_gems!(groups: ["doc"]) - HOMEBREW_LIBRARY_PATH.cd do + HOMEBREW_LIBRARY_PATH.cd do |dir| no_api_args = if args.only_public? ["--hide-api", "private", "--hide-api", "internal"] else [] end - system "bundle", "exec", "yard", "doc", "--output", "doc", *no_api_args + output_dir = dir/"doc" - exec_browser "file://#{HOMEBREW_LIBRARY_PATH}/doc/index.html" if args.open? + safe_system "bundle", "exec", "yard", "doc", "--fail-on-warning", *no_api_args, "--output", output_dir + + exec_browser "file://#{output_dir}/index.html" if args.open? end end end diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 2252caeb6e..162ae6fe76 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -77,11 +77,9 @@ class AbstractDownloadStrategy end # Disable any output during downloading. - # - # @deprecated sig { void } def shutup! - odeprecated "AbstractDownloadStrategy#shutup!", "AbstractDownloadStrategy#quiet!" + odeprecated "`AbstractDownloadStrategy#shutup!`", "`AbstractDownloadStrategy#quiet!`" quiet! end @@ -125,7 +123,6 @@ class AbstractDownloadStrategy end private :chdir - # @!attribute [r] source_modified_time # Returns the most recent modified time for all files in the current working directory after stage. # # @api public @@ -236,9 +233,7 @@ class VCSDownloadStrategy < AbstractDownloadStrategy version.respond_to?(:head?) && version.head? end - # @!attribute [r] last_commit - # Return last commit's unique identifier for the repository. - # Return most recent modified timestamp unless overridden. + # Return the most recent modified timestamp. # # @api public sig { returns(String) } @@ -733,7 +728,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy super end - # @see AbstractDownloadStrategy#source_modified_time + # Returns the most recent modified time for all files in the current working directory after stage. + # # @api public sig { returns(Time) } def source_modified_time @@ -747,7 +743,8 @@ class SubversionDownloadStrategy < VCSDownloadStrategy Time.parse time end - # @see VCSDownloadStrategy#last_commit + # Return last commit's unique identifier for the repository. + # # @api public sig { returns(String) } def last_commit @@ -847,7 +844,8 @@ class GitDownloadStrategy < VCSDownloadStrategy @ref ||= "master" end - # @see AbstractDownloadStrategy#source_modified_time + # Returns the most recent modified time for all files in the current working directory after stage. + # # @api public sig { returns(Time) } def source_modified_time @@ -855,7 +853,8 @@ class GitDownloadStrategy < VCSDownloadStrategy Time.parse(out) end - # @see VCSDownloadStrategy#last_commit + # Return last commit's unique identifier for the repository. + # # @api public sig { returns(String) } def last_commit @@ -1165,7 +1164,8 @@ class CVSDownloadStrategy < VCSDownloadStrategy end end - # @see AbstractDownloadStrategy#source_modified_time + # Returns the most recent modified time for all files in the current working directory after stage. + # # @api public sig { returns(Time) } def source_modified_time @@ -1240,7 +1240,8 @@ class MercurialDownloadStrategy < VCSDownloadStrategy @url = @url.sub(%r{^hg://}, "") end - # @see AbstractDownloadStrategy#source_modified_time + # Returns the most recent modified time for all files in the current working directory after stage. + # # @api public sig { returns(Time) } def source_modified_time @@ -1250,7 +1251,8 @@ class MercurialDownloadStrategy < VCSDownloadStrategy Time.parse(out) end - # @see VCSDownloadStrategy#last_commit + # Return last commit's unique identifier for the repository. + # # @api public sig { returns(String) } def last_commit @@ -1327,7 +1329,8 @@ class BazaarDownloadStrategy < VCSDownloadStrategy @url = @url.sub(%r{^bzr://}, "") end - # @see AbstractDownloadStrategy#source_modified_time + # Returns the most recent modified time for all files in the current working directory after stage. + # # @api public sig { returns(Time) } def source_modified_time @@ -1338,7 +1341,8 @@ class BazaarDownloadStrategy < VCSDownloadStrategy Time.parse(timestamp) end - # @see VCSDownloadStrategy#last_commit + # Return last commit's unique identifier for the repository. + # # @api public sig { returns(String) } def last_commit @@ -1390,7 +1394,8 @@ class FossilDownloadStrategy < VCSDownloadStrategy @url = @url.sub(%r{^fossil://}, "") end - # @see AbstractDownloadStrategy#source_modified_time + # Returns the most recent modified time for all files in the current working directory after stage. + # # @api public sig { returns(Time) } def source_modified_time @@ -1398,7 +1403,8 @@ class FossilDownloadStrategy < VCSDownloadStrategy Time.parse(out[/^uuid: +\h+ (.+)$/, 1]) end - # @see VCSDownloadStrategy#last_commit + # Return last commit's unique identifier for the repository. + # # @api public sig { returns(String) } def last_commit diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index ccb0daa382..bdcc50ef24 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -16,7 +16,6 @@ class UsageError < RuntimeError @reason = reason end - # @!visibility private sig { returns(String) } def to_s s = "Invalid usage" @@ -109,7 +108,6 @@ class FormulaOrCaskUnavailableError < RuntimeError "Did you mean #{similar_formula_names.to_sentence two_words_connector: " or ", last_word_connector: " or "}?" end - # @!visibility private sig { returns(String) } def to_s s = "No available formula or cask with the name \"#{name}\". #{did_you_mean}".strip @@ -129,7 +127,6 @@ class TapFormulaOrCaskUnavailableError < FormulaOrCaskUnavailableError @tap = tap end - # @!visibility private sig { returns(String) } def to_s s = super @@ -149,7 +146,6 @@ class FormulaUnavailableError < FormulaOrCaskUnavailableError " (dependency of #{dependent})" if dependent && dependent != name end - # @!visibility private sig { returns(String) } def to_s "No available formula with the name \"#{name}\"#{dependent_s}. #{did_you_mean}".strip @@ -160,7 +156,6 @@ end module FormulaClassUnavailableErrorModule attr_reader :path, :class_name, :class_list - # @!visibility private sig { returns(String) } def to_s s = super @@ -204,7 +199,6 @@ end module FormulaUnreadableErrorModule attr_reader :formula_error - # @!visibility private sig { returns(String) } def to_s "#{name}: " + formula_error.to_s @@ -233,7 +227,6 @@ class TapFormulaUnavailableError < FormulaUnavailableError super "#{tap}/#{name}" end - # @!visibility private sig { returns(String) } def to_s s = super @@ -572,7 +565,7 @@ class UnbottledError < RuntimeError end end -# Raised by Homebrew.install, Homebrew.reinstall, and Homebrew.upgrade +# Raised by `Homebrew.install`, `Homebrew.reinstall` and `Homebrew.upgrade` # if the user passes any flags/environment that would case a bottle-only # installation on a system without build tools to fail. class BuildFlagsError < RuntimeError diff --git a/Library/Homebrew/extend/ENV.rbi b/Library/Homebrew/extend/ENV.rbi index 0c7c926da8..dca2af30b3 100644 --- a/Library/Homebrew/extend/ENV.rbi +++ b/Library/Homebrew/extend/ENV.rbi @@ -1,5 +1,6 @@ # typed: strict +# @!visibility private module EnvMethods include Kernel @@ -39,6 +40,7 @@ module EnvActivation include Superenv end +# @!visibility private class Sorbet module Private module Static diff --git a/Library/Homebrew/extend/ENV/shared.rbi b/Library/Homebrew/extend/ENV/shared.rbi index b1eac4cd3e..1a6b66af46 100644 --- a/Library/Homebrew/extend/ENV/shared.rbi +++ b/Library/Homebrew/extend/ENV/shared.rbi @@ -4,6 +4,7 @@ module SharedEnvExtension include EnvMethods end +# @!visibility private class Sorbet module Private module Static diff --git a/Library/Homebrew/extend/array.rb b/Library/Homebrew/extend/array.rb index 152033304b..e68b1277a1 100644 --- a/Library/Homebrew/extend/array.rb +++ b/Library/Homebrew/extend/array.rb @@ -2,59 +2,72 @@ # frozen_string_literal: true class Array - # Equal to self[1]. + # Equal to `self[1]`. # - # %w( a b c d e ).second # => "b" + # ### Example + # + # ```ruby + # %w( a b c d e ).second # => "b" + # ``` def second = self[1] - # Equal to self[2]. + # Equal to `self[2]`. # - # %w( a b c d e ).third # => "c" + # ### Example + # + # ```ruby + # %w( a b c d e ).third # => "c" + # ``` def third = self[2] - # Equal to self[3]. + # Equal to `self[3]`. # - # %w( a b c d e ).fourth # => "d" + # ### Example + # + # ```ruby + # %w( a b c d e ).fourth # => "d" + # ``` def fourth = self[3] - # Equal to self[4]. + # Equal to `self[4]`. # - # %w( a b c d e ).fifth # => "e" + # ### Example + # + # ```ruby + # %w( a b c d e ).fifth # => "e" + # ``` def fifth = self[4] # Converts the array to a comma-separated sentence where the last element is # joined by the connector word. # - # You can pass the following kwargs to change the default behavior: + # ### Examples # - # * :words_connector - The sign or word used to join all but the last - # element in arrays with three or more elements (default: ", "). - # * :last_word_connector - The sign or word used to join the last element - # in arrays with three or more elements (default: ", and "). - # * :two_words_connector - The sign or word used to join the elements - # in arrays with two elements (default: " and "). + # ```ruby + # [].to_sentence # => "" + # ['one'].to_sentence # => "one" + # ['one', 'two'].to_sentence # => "one and two" + # ['one', 'two', 'three'].to_sentence # => "one, two and three" + # ['one', 'two'].to_sentence(two_words_connector: '-') + # # => "one-two" + # ``` # - # ==== Examples + # ``` + # ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ') + # # => "one or two or at least three" + # ``` # - # [].to_sentence # => "" - # ['one'].to_sentence # => "one" - # ['one', 'two'].to_sentence # => "one and two" - # ['one', 'two', 'three'].to_sentence # => "one, two, and three" - # ['one', 'two'].to_sentence(two_words_connector: '-') - # # => "one-two" - # - # ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ') - # # => "one or two or at least three" # @see https://github.com/rails/rails/blob/v7.0.4.2/activesupport/lib/active_support/core_ext/array/conversions.rb#L8-L84 # ActiveSupport Array#to_sentence monkey-patch # + # # Copyright (c) David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, - # distribute, sublicense, and/or sell copies of the Software, and to + # distribute, sublicense and/or sell copies of the Software and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # @@ -68,6 +81,14 @@ class Array # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + # + # + # @param [String] words_connector The sign or word used to join all but the last + # element in arrays with three or more elements (default: `", "`). + # @param [String] last_word_connector The sign or word used to join the last element + # in arrays with three or more elements (default: `" and "`). + # @param [String] two_words_connector The sign or word used to join the elements + # in arrays with two elements (default: `" and "`). sig { params(words_connector: String, two_words_connector: String, last_word_connector: String).returns(String) } def to_sentence(words_connector: ", ", two_words_connector: " and ", last_word_connector: " and ") case length diff --git a/Library/Homebrew/extend/blank.rb b/Library/Homebrew/extend/blank.rb index 9eb738e69d..85c5ea55b4 100644 --- a/Library/Homebrew/extend/blank.rb +++ b/Library/Homebrew/extend/blank.rb @@ -3,15 +3,20 @@ class Object # An object is blank if it's false, empty, or a whitespace string. - # For example, +nil+, '', ' ', [], {}, and +false+ are all blank. # - # This simplifies + # For example, `nil`, `''`, `' '`, `[]`, `{}` and `false` are all blank. # - # !address || address.empty? + # ### Example # - # to + # ```ruby + # !address || address.empty? + # ``` # - # address.blank? + # can be simplified to + # + # ```ruby + # address.blank? + # ``` sig { returns(T::Boolean) } def blank? respond_to?(:empty?) ? !!T.unsafe(self).empty? : false @@ -21,20 +26,23 @@ class Object sig { returns(T::Boolean) } def present? = !blank? - # Returns the receiver if it's present otherwise returns +nil+. - # object.presence is equivalent to + # Returns the receiver if it's present, otherwise returns `nil`. # - # object.present? ? object : nil + # `object.presence` is equivalent to `object.present? ? object : nil`. # - # For example, something like + # ### Example # - # state = params[:state] if params[:state].present? - # country = params[:country] if params[:country].present? - # region = state || country || 'US' + # ```ruby + # state = params[:state] if params[:state].present? + # country = params[:country] if params[:country].present? + # region = state || country || 'US' + # ``` # - # becomes + # can be simplified to # - # region = params[:state].presence || params[:country].presence || 'US' + # ```ruby + # region = params[:state].presence || params[:country].presence || 'US' + # ``` sig { returns(T.nilable(T.self_type)) } def presence self if present? @@ -42,9 +50,11 @@ class Object end class NilClass - # +nil+ is blank: + # `nil` is blank: # - # nil.blank? # => true + # ```ruby + # nil.blank? # => true + # ``` sig { returns(TrueClass) } def blank? = true @@ -53,9 +63,11 @@ class NilClass end class FalseClass - # +false+ is blank: + # `false` is blank: # - # false.blank? # => true + # ```ruby + # false.blank? # => true + # ``` sig { returns(TrueClass) } def blank? = true @@ -64,9 +76,11 @@ class FalseClass end class TrueClass - # +true+ is not blank: + # `true` is not blank: # - # true.blank? # => false + # ```ruby + # true.blank? # => false + # ``` sig { returns(FalseClass) } def blank? = false @@ -77,11 +91,12 @@ end class Array # An array is blank if it's empty: # - # [].blank? # => true - # [1,2,3].blank? # => false - # - # @return [true, false] - alias blank? empty? + # ```ruby + # [].blank? # => true + # [1,2,3].blank? # => false + # ``` + sig { returns(T::Boolean) } + def blank? = empty? sig { returns(T::Boolean) } def present? = !empty? # :nodoc: @@ -90,11 +105,13 @@ end class Hash # A hash is blank if it's empty: # - # {}.blank? # => true - # { key: 'value' }.blank? # => false # - # @return [true, false] - alias blank? empty? + # ```ruby + # {}.blank? # => true + # { key: 'value' }.blank? # => false + # ``` + sig { returns(T::Boolean) } + def blank? = empty? sig { returns(T::Boolean) } def present? = !empty? # :nodoc: @@ -103,9 +120,12 @@ end class Symbol # A Symbol is blank if it's empty: # - # :''.blank? # => true - # :symbol.blank? # => false - alias blank? empty? + # ```ruby + # :''.blank? # => true + # :symbol.blank? # => false + # ``` + sig { returns(T::Boolean) } + def blank? = empty? sig { returns(T::Boolean) } def present? = !empty? # :nodoc: @@ -122,14 +142,18 @@ class String # A string is blank if it's empty or contains whitespaces only: # - # ''.blank? # => true - # ' '.blank? # => true - # "\t\n\r".blank? # => true - # ' blah '.blank? # => false + # ```ruby + # ''.blank? # => true + # ' '.blank? # => true + # "\t\n\r".blank? # => true + # ' blah '.blank? # => false + # ``` # # Unicode whitespace is supported: # - # "\u00a0".blank? # => true + # ```ruby + # "\u00a0".blank? # => true + # ``` sig { returns(T::Boolean) } def blank? # The regexp that matches blank strings is expensive. For the case of empty @@ -150,8 +174,10 @@ end class Numeric # :nodoc: # No number is blank: # - # 1.blank? # => false - # 0.blank? # => false + # ```ruby + # 1.blank? # => false + # 0.blank? # => false + # ``` sig { returns(FalseClass) } def blank? = false @@ -162,7 +188,9 @@ end class Time # :nodoc: # No Time is blank: # - # Time.now.blank? # => false + # ```ruby + # Time.now.blank? # => false + # ``` sig { returns(FalseClass) } def blank? = false diff --git a/Library/Homebrew/extend/enumerable.rb b/Library/Homebrew/extend/enumerable.rb index 77b499b2dd..5f8ca22f17 100644 --- a/Library/Homebrew/extend/enumerable.rb +++ b/Library/Homebrew/extend/enumerable.rb @@ -2,7 +2,7 @@ # frozen_string_literal: true module Enumerable - # The negative of the Enumerable#include?. Returns +true+ if the + # The negative of the {Enumerable#include?}. Returns `true` if the # collection does not include the object. sig { params(object: T.untyped).returns(T::Boolean) } def exclude?(object) = !include?(object) @@ -10,21 +10,29 @@ module Enumerable # Returns a new +Array+ without the blank items. # Uses Object#blank? for determining if an item is blank. # - # [1, "", nil, 2, " ", [], {}, false, true].compact_blank - # # => [1, 2, true] + # ### Examples # - # Set.new([nil, "", 1, false]).compact_blank - # # => [1] + # ``` + # [1, "", nil, 2, " ", [], {}, false, true].compact_blank + # # => [1, 2, true] + # ``` # - # When called on a +Hash+, returns a new +Hash+ without the blank values. + # ```ruby + # Set.new([nil, "", 1, false]).compact_blank + # # => [1] + # ``` # - # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank - # # => { b: 1, f: true } + # When called on a {Hash}, returns a new {Hash} without the blank values. + # + # ```ruby + # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank + # # => { b: 1, f: true } + # ``` sig { returns(T.self_type) } def compact_blank = T.unsafe(self).reject(&:blank?) end class Hash - # Hash#reject has its own definition, so this needs one too. + # {Hash#reject} has its own definition, so this needs one too. def compact_blank = reject { |_k, v| T.unsafe(v).blank? } end diff --git a/Library/Homebrew/extend/hash/deep_merge.rb b/Library/Homebrew/extend/hash/deep_merge.rb index 01ecbe9260..527e36076b 100644 --- a/Library/Homebrew/extend/hash/deep_merge.rb +++ b/Library/Homebrew/extend/hash/deep_merge.rb @@ -2,25 +2,31 @@ # frozen_string_literal: true class Hash - # Returns a new hash with +self+ and +other_hash+ merged recursively. + # Returns a new hash with `self` and `other_hash` merged recursively. # - # h1 = { a: true, b: { c: [1, 2, 3] } } - # h2 = { a: false, b: { x: [3, 4, 5] } } + # ### Examples # - # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } } + # ```ruby + # h1 = { a: true, b: { c: [1, 2, 3] } } + # h2 = { a: false, b: { x: [3, 4, 5] } } + # + # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } } + # ``` # # Like with Hash#merge in the standard library, a block can be provided # to merge values: # - # h1 = { a: 100, b: 200, c: { c1: 100 } } - # h2 = { b: 250, c: { c1: 200 } } - # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val } - # # => { a: 100, b: 450, c: { c1: 300 } } + # ```ruby + # h1 = { a: 100, b: 200, c: { c1: 100 } } + # h2 = { b: 250, c: { c1: 200 } } + # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val } + # # => { a: 100, b: 450, c: { c1: 300 } } + # ``` def deep_merge(other_hash, &block) dup.deep_merge!(other_hash, &block) end - # Same as +deep_merge+, but modifies +self+. + # Same as {#deep_merge}, but modifies `self`. def deep_merge!(other_hash, &block) merge!(other_hash) do |key, this_val, other_val| if T.unsafe(this_val).is_a?(Hash) && other_val.is_a?(Hash) diff --git a/Library/Homebrew/extend/hash/deep_transform_values.rb b/Library/Homebrew/extend/hash/deep_transform_values.rb index 2787efc1f6..be366f1b14 100644 --- a/Library/Homebrew/extend/hash/deep_transform_values.rb +++ b/Library/Homebrew/extend/hash/deep_transform_values.rb @@ -6,11 +6,14 @@ class Hash # This includes the values from the root hash and from all # nested hashes and arrays. # - # @example - # hash = { person: { name: 'Rob', age: '28' } } + # ### Example # - # hash.deep_transform_values{ |value| value.to_s.upcase } - # # => {person: {name: "ROB", age: "28"}} + # ```ruby + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_transform_values{ |value| value.to_s.upcase } + # # => {person: {name: "ROB", age: "28"}} + # ``` def deep_transform_values(&block) = _deep_transform_values_in_object(self, &block) # Destructively converts all values by using the block operation. diff --git a/Library/Homebrew/extend/hash/keys.rb b/Library/Homebrew/extend/hash/keys.rb index 06878a4ce0..fc0cbfbe59 100644 --- a/Library/Homebrew/extend/hash/keys.rb +++ b/Library/Homebrew/extend/hash/keys.rb @@ -5,14 +5,18 @@ class Hash # Validates all keys in a hash match `*valid_keys`, raising # `ArgumentError` on a mismatch. # - # Note that keys are treated differently than HashWithIndifferentAccess, + # Note that keys are treated differently than `HashWithIndifferentAccess`, # meaning that string and symbol keys will not match. # - # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) - # # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age" - # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') - # # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'" - # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing + # ### Example# + # + # ```ruby + # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) + # # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age" + # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') + # # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'" + # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing + # ``` sig { params(valid_keys: T.untyped).void } def assert_valid_keys(*valid_keys) valid_keys.flatten! @@ -28,10 +32,14 @@ class Hash # This includes the keys from the root hash and from all # nested hashes and arrays. # - # hash = { person: { name: 'Rob', age: '28' } } + # ### Example # - # hash.deep_transform_keys{ |key| key.to_s.upcase } - # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}} + # ```ruby + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_transform_keys{ |key| key.to_s.upcase } + # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}} + # ``` def deep_transform_keys(&block) = _deep_transform_keys_in_object(self, &block) # Destructively converts all keys by using the block operation. @@ -43,10 +51,14 @@ class Hash # This includes the keys from the root hash and from all # nested hashes and arrays. # - # hash = { person: { name: 'Rob', age: '28' } } + # ### Example # - # hash.deep_stringify_keys - # # => {"person"=>{"name"=>"Rob", "age"=>"28"}} + # ```ruby + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_stringify_keys + # # => {"person"=>{"name"=>"Rob", "age"=>"28"}} + # ``` def deep_stringify_keys = T.unsafe(self).deep_transform_keys(&:to_s) # Destructively converts all keys to strings. @@ -55,13 +67,17 @@ class Hash def deep_stringify_keys! = T.unsafe(self).deep_transform_keys!(&:to_s) # Returns a new hash with all keys converted to symbols, as long as - # they respond to +to_sym+. This includes the keys from the root hash + # they respond to `to_sym`. This includes the keys from the root hash # and from all nested hashes and arrays. # - # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } } + # ### Example # - # hash.deep_symbolize_keys - # # => {:person=>{:name=>"Rob", :age=>"28"}} + # ```ruby + # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } } + # + # hash.deep_symbolize_keys + # # => {:person=>{:name=>"Rob", :age=>"28"}} + # ``` def deep_symbolize_keys deep_transform_keys do |key| T.unsafe(key).to_sym @@ -71,7 +87,7 @@ class Hash end # Destructively converts all keys to symbols, as long as they respond - # to +to_sym+. This includes the keys from the root hash and from all + # to `to_sym`. This includes the keys from the root hash and from all # nested hashes and arrays. def deep_symbolize_keys! deep_transform_keys! do |key| @@ -102,7 +118,7 @@ class Hash def _deep_transform_keys_in_object!(object, &block) case object when Hash - # We can't use `each_key` here because we're updating the hash in-place + # We can't use `each_key` here because we're updating the hash in-place. object.keys.each do |key| # rubocop:disable Style/HashEachMethods value = object.delete(key) object[yield(key)] = _deep_transform_keys_in_object!(value, &block) diff --git a/Library/Homebrew/extend/kernel.rb b/Library/Homebrew/extend/kernel.rb index d9f0f2aa6f..8696c5cc6b 100644 --- a/Library/Homebrew/extend/kernel.rb +++ b/Library/Homebrew/extend/kernel.rb @@ -493,14 +493,20 @@ module Kernel end # Calls the given block with the passed environment variables - # added to ENV, then restores ENV afterwards. - #
with_env(PATH: "/bin") do
-  #   system "echo $PATH"
-  # end
+ # added to `ENV`, then restores `ENV` afterwards. + # + # NOTE: This method is **not** thread-safe – other threads + # which happen to be scheduled during the block will also + # see these environment variables. + # + # ### Example + # + # ```ruby + # with_env(PATH: "/bin") do + # system "echo $PATH" + # end + # ``` # - # @note This method is *not* thread-safe - other threads - # which happen to be scheduled during the block will also - # see these environment variables. # @api public def with_env(hash) old_values = {} diff --git a/Library/Homebrew/extend/object/duplicable.rb b/Library/Homebrew/extend/object/duplicable.rb index d5f566cb52..a0f0462084 100644 --- a/Library/Homebrew/extend/object/duplicable.rb +++ b/Library/Homebrew/extend/object/duplicable.rb @@ -1,24 +1,30 @@ # typed: strict # frozen_string_literal: true -#-- # Most objects are cloneable, but not all. For example you can't dup methods: # -# method(:puts).dup # => TypeError: allocator undefined for Method +# ```ruby +# method(:puts).dup # => TypeError: allocator undefined for Method +# ``` # # Classes may signal their instances are not duplicable removing +dup+/+clone+ # or raising exceptions from them. So, to dup an arbitrary object you normally # use an optimistic approach and are ready to catch an exception, say: # -# arbitrary_object.dup rescue object +# ```ruby +# arbitrary_object.dup rescue object +# ``` # # Rails dups objects in a few critical spots where they are not that arbitrary. -# That rescue is very expensive (like 40 times slower than a predicate), and it +# That `rescue` is very expensive (like 40 times slower than a predicate) and it # is often triggered. # # That's why we hardcode the following cases and check duplicable? instead of # using that rescue idiom. -#++ +# rubocop:disable Layout/EmptyLines + + +# rubocop:enable Layout/EmptyLines class Object # Can you safely dup this object? # @@ -31,8 +37,10 @@ end class Method # Methods are not duplicable: # - # method(:puts).duplicable? # => false - # method(:puts).dup # => TypeError: allocator undefined for Method + # ```ruby + # method(:puts).duplicable? # => false + # method(:puts).dup # => TypeError: allocator undefined for Method + # ``` sig { returns(FalseClass) } def duplicable? = false end @@ -40,8 +48,10 @@ end class UnboundMethod # Unbound methods are not duplicable: # - # method(:puts).unbind.duplicable? # => false - # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod + # ```ruby + # method(:puts).unbind.duplicable? # => false + # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod + # ``` sig { returns(FalseClass) } def duplicable? = false end @@ -51,7 +61,9 @@ require "singleton" module Singleton # Singleton instances are not duplicable: # - # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton + # ```ruby + # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton + # ``` sig { returns(FalseClass) } def duplicable? = false end diff --git a/Library/Homebrew/extend/os/linux/parser.rb b/Library/Homebrew/extend/os/linux/parser.rb index fcbeb67f0b..9d76e9c9b3 100644 --- a/Library/Homebrew/extend/os/linux/parser.rb +++ b/Library/Homebrew/extend/os/linux/parser.rb @@ -16,7 +16,7 @@ module Homebrew return unless @args.cask? # NOTE: We don't raise an error here because we don't want - # to print the help page or a stack trace. + # to print the help page or a stack trace. odie "Invalid `--cask` usage: Casks do not work on Linux" end end diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb index c963cf4742..37a3a335fd 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb @@ -27,12 +27,11 @@ module Stdenv append "LDFLAGS", "-Wl,-headerpad_max_install_names" - # sed is strict, and errors out when it encounters files with - # mixed character sets + # `sed` is strict and errors out when it encounters files with mixed character sets. delete("LC_ALL") self["LC_CTYPE"] = "C" - # Add lib and include etc. from the current macosxsdk to compiler flags: + # Add `lib` and `include` etc. from the current `macosxsdk` to compiler flags: macosxsdk(formula: @formula, testing_formula:) return unless MacOS::Xcode.without_clt? @@ -42,8 +41,8 @@ module Stdenv end def remove_macosxsdk(version = nil) - # Clear all lib and include dirs from CFLAGS, CPPFLAGS, LDFLAGS that were - # previously added by macosxsdk + # Clear all `lib` and `include` dirs from `CFLAGS`, `CPPFLAGS`, `LDFLAGS` that were + # previously added by `macosxsdk`. remove_from_cflags(/ ?-mmacosx-version-min=\d+\.\d+/) delete("CPATH") remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib" @@ -58,14 +57,14 @@ module Stdenv if HOMEBREW_PREFIX.to_s == "/usr/local" delete("CMAKE_PREFIX_PATH") else - # It was set in setup_build_environment, so we have to restore it here. + # It was set in `setup_build_environment`, so we have to restore it here. self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s end remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks" end def macosxsdk(version = nil, formula: nil, testing_formula: false) - # Sets all needed lib and include dirs to CFLAGS, CPPFLAGS, LDFLAGS. + # Sets all needed `lib` and `include` dirs to `CFLAGS`, `CPPFLAGS`, `LDFLAGS`. remove_macosxsdk min_version = version || MacOS.version append_to_cflags("-mmacosx-version-min=#{min_version}") diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb index 72df60a253..0bcd281b2c 100644 --- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb +++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb @@ -83,8 +83,8 @@ module Hardware sysctl_bool("hw.optional.sse4_2") end - # NOTE: this is more reliable than checking uname. - # `sysctl` returns the right answer even when running in Rosetta 2. + # NOTE: This is more reliable than checking `uname`. `sysctl` returns + # the right answer even when running in Rosetta 2. def physical_cpu_arm64? sysctl_bool("hw.optional.arm64") end diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index d2c19de115..8b0c072d4c 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -126,10 +126,11 @@ class Pathname mkpath - # Use FileUtils.mv over File.rename to handle filesystem boundaries. If src - # is a symlink, and its target is moved first, FileUtils.mv will fail: - # https://bugs.ruby-lang.org/issues/7707 - # In that case, use the system "mv" command. + # Use `FileUtils.mv` over `File.rename` to handle filesystem boundaries. If `src` + # is a symlink and its target is moved first, `FileUtils.mv` will fail + # (https://bugs.ruby-lang.org/issues/7707). + # + # In that case, use the system `mv` command. if src.symlink? raise unless Kernel.system "mv", src.to_s, dst else @@ -178,7 +179,9 @@ class Pathname T.unsafe(self).open("a", **open_args) { |f| f.puts(content) } end - # @note This always overwrites. + # Write to a file atomically. + # + # NOTE: This always overwrites. # # @api public sig { params(content: String).void } @@ -201,6 +204,7 @@ class Pathname # Changing file ownership failed, moving on. nil end + begin # This operation will affect filesystem ACL's chmod(old_stat.mode) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 0d2c5a5508..6175f9abc9 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -48,7 +48,10 @@ require "extend/api_hashable" # @see https://docs.brew.sh/Formula-Cookbook Formula Cookbook # @see https://rubystyle.guide Ruby Style Guide # -#
class Wget < Formula
+# ### Example
+#
+# ```ruby
+# class Wget < Formula
 #   homepage "https://www.gnu.org/software/wget/"
 #   url "https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
 #   sha256 "52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"
@@ -57,7 +60,8 @@ require "extend/api_hashable"
 #     system "./configure", "--prefix=#{prefix}"
 #     system "make", "install"
 #   end
-# end
+# end +# ``` class Formula include FileUtils include Utils::Shebang @@ -543,15 +547,20 @@ class Formula # A named {Resource} for the currently active {SoftwareSpec}. # Additional downloads can be defined as {#resource}s. # {Resource#stage} will create a temporary directory and yield to a block. - #
resource("additional_files").stage { bin.install "my/extra/tool" }
- # @!method resource - delegate resource: :active_spec + # + # ### Example + # + # ```ruby + # resource("additional_files").stage { bin.install "my/extra/tool" } + # ``` + def resource(name) + active_spec.resource(name) + end # An old name for the formula. - # @deprecated Use {#oldnames} instead. sig { returns(T.nilable(String)) } def oldname - odisabled "Formula#oldname", "Formula#oldnames" + odisabled "`Formula#oldname`", "`Formula#oldnames`" @oldname ||= oldnames.first end @@ -589,12 +598,14 @@ class Formula delegate declared_deps: :active_spec # Dependencies provided by macOS for the currently active {SoftwareSpec}. - # @deprecated - delegate uses_from_macos_elements: :active_spec + def uses_from_macos_elements + odisabled "`Formula#uses_from_macos_elements`", "`Formula#declared_deps`" + end # Dependency names provided by macOS for the currently active {SoftwareSpec}. - # @deprecated - delegate uses_from_macos_names: :active_spec + def uses_from_macos_names + odisabled "`Formula#uses_from_macos_names`", "`Formula#declared_deps`" + end # The {Requirement}s for the currently active {SoftwareSpec}. delegate requirements: :active_spec @@ -760,11 +771,19 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Examples + # # Need to install into the {.bin} but the makefile doesn't `mkdir -p prefix/bin`? - #
bin.mkpath
+ # + # ```ruby + # bin.mkpath + # ``` # # No `make install` available? - #
bin.install "binary1"
+ # + # ```ruby + # bin.install "binary1" + # ``` # # @api public sig { returns(Pathname) } @@ -786,8 +805,13 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Example + # # No `make install` available? - #
include.install "example.h"
+ # + # ```ruby + # include.install "example.h" + # ``` # # @api public sig { returns(Pathname) } @@ -809,8 +833,13 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Example + # # No `make install` available? - #
lib.install "example.dylib"
+ # + # ```ruby + # lib.install "example.dylib" + # ``` # # @api public sig { returns(Pathname) } @@ -823,9 +852,13 @@ class Formula # It is commonly used to install files that we do not wish to be # symlinked into `HOMEBREW_PREFIX` from one of the other directories and # instead manually create symlinks or wrapper scripts into e.g. {#bin}. - #
libexec.install "foo.jar"
+  #
+  # ### Example
+  #
+  # ```ruby
+  # libexec.install "foo.jar"
   # bin.write_jar_script libexec/"foo.jar", "foo"
-  # 
+ # ``` # # @api public sig { returns(Pathname) } @@ -849,8 +882,13 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Example + # # No `make install` available? - #
man1.install "example.1"
+ # + # ```ruby + # man1.install "example.1" + # ``` # # @api public sig { returns(Pathname) } @@ -872,8 +910,13 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Example + # # No `make install` available? - #
man3.install "man.3"
+ # + # ```ruby + # man3.install "man.3" + # ``` # # @api public sig { returns(Pathname) } @@ -946,17 +989,31 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Examples + # # Need a custom directory? - #
(share/"concept").mkpath
+ # + # ```ruby + # (share/"concept").mkpath + # ``` # # Installing something into another custom directory? - #
(share/"concept2").install "ducks.txt"
+ # + # ```ruby + # (share/"concept2").install "ducks.txt" + # ``` # # Install `./example_code/simple/ones` to `share/demos`: - #
(share/"demos").install "example_code/simple/ones"
+ # + # ```ruby + # (share/"demos").install "example_code/simple/ones" + # ``` # # Install `./example_code/simple/ones` to `share/demos/examples`: - #
(share/"demos").install "example_code/simple/ones" => "examples"
+ # + # ```ruby + # (share/"demos").install "example_code/simple/ones" => "examples" + # ``` # # @api public sig { returns(Pathname) } @@ -969,8 +1026,13 @@ class Formula # This is symlinked into `HOMEBREW_PREFIX` after installation or with # `brew link` for formulae that are not keg-only. # + # ### Example + # # No `make install` available? - #
pkgshare.install "examples"
+ # + # ```ruby + # pkgshare.install "examples" + # ``` # # @api public sig { returns(Pathname) } @@ -981,8 +1043,13 @@ class Formula # The directory where Emacs Lisp files should be installed, with the # formula name appended to avoid linking conflicts. # + # ### Example + # # To install an Emacs mode included with a software package: - #
elisp.install "contrib/emacs/example-mode.el"
+ # + # ```ruby + # elisp.install "contrib/emacs/example-mode.el" + # ``` # # @api public sig { returns(Pathname) } @@ -1134,8 +1201,11 @@ class Formula end # This method can be overridden to provide a plist. - # @see https://www.unix.com/man-page/all/5/plist/ Apple's plist(5) man page - #
def plist; <<~EOS
+  #
+  # ### Example
+  #
+  # ```ruby
+  # def plist; <<~EOS
   #   
   #   
   #   
@@ -1158,11 +1228,13 @@ class Formula
   #   
   #   
   #   EOS
-  # end
+ # end + # ``` # - # @deprecated Please use {Homebrew::Service} instead. + # @see https://www.unix.com/man-page/all/5/plist/ plist(5) man page def plist # odeprecated: consider removing entirely in 4.3.0 + # odeprecated "`Formula#plist`", "`Homebrew::Service`" nil end @@ -1207,7 +1279,12 @@ class Formula # # This is the preferred way to refer to a formula in plists or from another # formula, as the path is stable even when the software is updated. - #
args << "--with-readline=#{Formula["readline"].opt_prefix}" if build.with? "readline"
+ # + # ### Example + # + # ```ruby + # args << "--with-readline=#{Formula["readline"].opt_prefix}" if build.with? "readline" + # ``` # # @api public sig { returns(Pathname) } @@ -1353,14 +1430,19 @@ class Formula # Warn the user about any Homebrew-specific issues or quirks for this package. # These should not contain setup instructions that would apply to installation # through a different package manager on a different OS. - # @return [String] - #
def caveats
+  #
+  # ### Example
+  #
+  # ```ruby
+  # def caveats
   #   <<~EOS
   #     Are optional. Something the user must be warned about?
   #   EOS
-  # end
+ # end + # ``` # - #
def caveats
+  # ```ruby
+  # def caveats
   #   s = <<~EOS
   #     Print some important notice to the user when `brew info [formula]` is
   #     called or when brewing a formula.
@@ -1368,7 +1450,8 @@ class Formula
   #   EOS
   #   s += "Some issue only on older systems" if MacOS.version < :el_capitan
   #   s
-  # end
+ # end + # ``` sig { overridable.returns(T.nilable(String)) } def caveats nil @@ -1656,6 +1739,7 @@ class Formula delegate pinnable?: :@pin + # !attr[r] pinned? # @api internal delegate pinned?: :@pin @@ -1687,11 +1771,9 @@ class Formula end # @api public - # @!visibility private sig { returns(String) } def to_s = name - # @!visibility private sig { returns(String) } def inspect "#" @@ -1793,11 +1875,14 @@ class Formula # # If `name` is specified as "*", match any shared library of any version. # - #
shared_library("foo")      #=> foo.dylib
+  # ### Example
+  #
+  # ```ruby
+  # shared_library("foo")      #=> foo.dylib
   # shared_library("foo", 1)   #=> foo.1.dylib
   # shared_library("foo", "*") #=> foo.2.dylib, foo.1.dylib, foo.dylib
   # shared_library("*")        #=> foo.dylib, bar.dylib
-  # 
+ # ``` sig { params(name: String, version: T.nilable(T.any(String, Integer))).returns(String) } def shared_library(name, version = nil) return "*.dylib" if name == "*" && (version.blank? || version == "*") @@ -1815,10 +1900,13 @@ class Formula # Optionally specify a `source` or `target` depending on the location # of the file containing the RPATH command and where its target is located. # - #
rpath #=> "@loader_path/../lib"
+  # ### Example
+  #
+  # ```ruby
+  # rpath #=> "@loader_path/../lib"
   # rpath(target: frameworks) #=> "@loader_path/../Frameworks"
   # rpath(source: libexec/"bin") #=> "@loader_path/../../lib"
-  # 
+ # ``` sig { params(source: Pathname, target: Pathname).returns(String) } def rpath(source: bin, target: lib) unless target.to_s.start_with?(HOMEBREW_PREFIX) @@ -1880,68 +1968,96 @@ class Formula end private :extract_macho_slice_from - # Generate shell completions for a formula for bash, zsh, and fish, using the formula's executable. + # Generate shell completions for a formula for `bash`, `zsh` and `fish`, using the formula's executable. # - # @param commands [Pathname, String] the path to the executable and any passed subcommand(s) - # to use for generating the completion scripts. - # @param base_name [String] the base name of the generated completion script. Defaults to the formula name. - # @param shells [Array] the shells to generate completion scripts for. Defaults to `[:bash, :zsh, :fish]`. - # @param shell_parameter_format [String, Symbol] specify how `shells` should each be passed - # to the `executable`. Takes either a String representing a prefix, or one of `[:flag, :arg, :none, :click]`. - # Defaults to plainly passing the shell. + # ### Examples # - # @example Using default values for optional arguments - # generate_completions_from_executable(bin/"foo", "completions") + # Using default values for optional arguments. # - # # translates to - # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "bash") - # (zsh_completion/"_foo").write Utils.safe_popen_read({ "SHELL" => "zsh" }, bin/"foo", "completions", "zsh") - # (fish_completion/"foo.fish").write Utils.safe_popen_read({ "SHELL" => "fish" }, bin/"foo", - # "completions", "fish") + # ```ruby + # generate_completions_from_executable(bin/"foo", "completions") # - # @example Selecting shells and using a different `base_name` - # generate_completions_from_executable(bin/"foo", "completions", shells: [:bash, :zsh], base_name: "bar") + # # translates to + # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "bash") + # (zsh_completion/"_foo").write Utils.safe_popen_read({ "SHELL" => "zsh" }, bin/"foo", "completions", "zsh") + # (fish_completion/"foo.fish").write Utils.safe_popen_read({ "SHELL" => "fish" }, bin/"foo", + # "completions", "fish") + # ``` # - # # translates to - # (bash_completion/"bar").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "bash") - # (zsh_completion/"_bar").write Utils.safe_popen_read({ "SHELL" => "zsh" }, bin/"foo", "completions", "zsh") + # Selecting shells and using a different `base_name`. # - # @example Using predefined `shell_parameter_format :flag` - # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :flag, shells: [:bash]) + # ```ruby + # generate_completions_from_executable(bin/"foo", "completions", shells: [:bash, :zsh], base_name: "bar") # - # # translates to - # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "--bash") + # # translates to + # (bash_completion/"bar").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "bash") + # (zsh_completion/"_bar").write Utils.safe_popen_read({ "SHELL" => "zsh" }, bin/"foo", "completions", "zsh") + # ``` # - # @example Using predefined `shell_parameter_format :arg` - # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :arg, shells: [:bash]) + # Using predefined `shell_parameter_format :flag`. # - # # translates to - # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", - # "completions", "--shell=bash") + # ```ruby + # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :flag, shells: [:bash]) # - # @example Using predefined `shell_parameter_format :none` - # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :none, shells: [:bash]) + # # translates to + # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "--bash") + # ``` # - # # translates to - # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions") + # Using predefined `shell_parameter_format :arg`. # - # @example Using predefined `shell_parameter_format :click` - # generate_completions_from_executable(bin/"foo", shell_parameter_format: :click, shells: [:zsh]) + # ```ruby + # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :arg, shells: [:bash]) # - # # translates to - # (zsh_completion/"_foo").write Utils.safe_popen_read({ "SHELL" => "zsh", "_FOO_COMPLETE" => "zsh_source" }, - # bin/"foo") + # # translates to + # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", + # "completions", "--shell=bash") + # ``` # - # @example Using custom `shell_parameter_format` - # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: "--selected-shell=", - # shells: [:bash]) + # Using predefined `shell_parameter_format :none`. # - # # translates to - # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", - # "completions", "--selected-shell=bash") + # ```ruby + # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :none, shells: [:bash]) + # + # # translates to + # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions") + # ``` + # + # Using predefined `shell_parameter_format :click`. + # + # ```ruby + # generate_completions_from_executable(bin/"foo", shell_parameter_format: :click, shells: [:zsh]) + # + # # translates to + # (zsh_completion/"_foo").write Utils.safe_popen_read({ "SHELL" => "zsh", "_FOO_COMPLETE" => "zsh_source" }, + # bin/"foo") + # ``` + # + # Using custom `shell_parameter_format`. + # + # ```ruby + # generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: "--selected-shell=", + # shells: [:bash]) + # + # # translates to + # (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", + # "completions", "--selected-shell=bash") + # ``` + # + # @param commands [Pathname, String] + # the path to the executable and any passed subcommand(s) to use for generating the completion scripts. + # @param base_name [String] + # the base name of the generated completion script. Defaults to the formula name. + # @param shells [Array] + # the shells to generate completion scripts for. Defaults to `[:bash, :zsh, :fish]`. + # @param shell_parameter_format [String, Symbol] + # specify how `shells` should each be passed to the `executable`. Takes either a String representing a + # prefix, or one of `[:flag, :arg, :none, :click]`. Defaults to plainly passing the shell. sig { - params(commands: T.any(Pathname, String), base_name: String, shells: T::Array[Symbol], - shell_parameter_format: T.nilable(T.any(Symbol, String))).void + params( + commands: T.any(Pathname, String), + base_name: String, shells: T::Array[Symbol], + shell_parameter_format: T.nilable(T.any(Symbol, String)) + ).void } def generate_completions_from_executable(*commands, base_name: name, @@ -2129,8 +2245,10 @@ class Formula delegate env: :"self.class" + # !attr[r] conflicts # @api internal - delegate conflicts: :"self.class" + sig { returns(T::Array[FormulaConflict]) } + def conflicts = self.class.conflicts # Returns a list of Dependency objects in an installable order, which # means if a depends on b then b will be ordered before a in this list @@ -2700,10 +2818,15 @@ class Formula # installation instructions. The sources (from {.url}) are downloaded, # hash-checked and then Homebrew changes into a temporary directory where the # archive is unpacked or repository cloned. - #
def install
+  #
+  # ### Example
+  #
+  # ```ruby
+  # def install
   #   system "./configure", "--prefix=#{prefix}"
   #   system "make", "install"
-  # end
+ # end + # ``` def install; end # Sometimes we have to change a bit before we install. Mostly we @@ -2713,14 +2836,21 @@ class Formula # defined by the formula, as only `HOMEBREW_PREFIX` is available # in the {DATAPatch embedded patch}. # + # ### Examples + # # `inreplace` supports regular expressions: - #
inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool"
+ # + # ```ruby + # inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool" + # ``` # # `inreplace` supports blocks: - #
inreplace "Makefile" do |s|
+  #
+  # ```ruby
+  # inreplace "Makefile" do |s|
   #   s.gsub! "/usr/local", HOMEBREW_PREFIX.to_s
   # end
-  # 
+ # ``` # # @see Utils::Inreplace.inreplace # @api public @@ -2780,26 +2910,43 @@ class Formula # To call out to the system, we use the `system` method and we prefer # you give the args separately as in the line below, otherwise a subshell # has to be opened first. - #
system "./bootstrap.sh", "--arg1", "--prefix=#{prefix}"
+ # + # ### Examples + # + # ```ruby + # system "./bootstrap.sh", "--arg1", "--prefix=#{prefix}" + # ``` # # For CMake and other build systems we have some necessary defaults in e.g. # {#std_cmake_args}: - #
system "cmake", ".", *std_cmake_args
+ # + # ```ruby + # system "cmake", ".", *std_cmake_args + # ``` # # If the arguments given to `configure` (or `make` or `cmake`) are depending # on options defined above, we usually make a list first and then # use the `args << if ` to append each: - #
args = ["--with-option1", "--with-option2"]
-  # args << "--without-gcc" if ENV.compiler == :clang
   #
-  # # Most software still uses `configure` and `make`.
-  # # Check with `./configure --help` for what our options are.
+  # ```ruby
+  # args = ["--with-option1", "--with-option2"]
+  # args << "--without-gcc" if ENV.compiler == :clang
+  # ```
+  #
+  # Most software still uses `configure` and `make`.
+  # Check with `./configure --help` for what our options are.
+  #
+  # ```ruby
   # system "./configure", "--disable-debug", "--disable-dependency-tracking",
   #                       "--disable-silent-rules", "--prefix=#{prefix}",
   #                       *args # our custom arg list (needs `*` to unpack)
+  # ```
   #
-  # # If there is a "make install" available, please use it!
-  # system "make", "install"
+ # If there is a "make install" available, please use it! + # + # ```ruby + # system "make", "install" + # ``` sig { params(cmd: T.any(String, Pathname), args: T.any(String, Integer, Pathname, Symbol)).void } def system(cmd, *args) verbose_using_dots = Homebrew::EnvConfig.verbose_using_dots? @@ -3138,36 +3285,65 @@ class Formula # of the software and Homebrew maintainers. # Shows when running `brew info`. # - #
desc "Example formula"
+ # ### Example + # + # ```ruby + # desc "Example formula" + # ``` # # @!attribute [w] desc # @api public attr_rw :desc - # @!attribute [w] license # The SPDX ID of the open-source license that the formula uses. # Shows when running `brew info`. + # # Use `:any_of`, `:all_of` or `:with` to describe complex license expressions. # `:any_of` should be used when the user can choose which license to use. # `:all_of` should be used when the user must use all licenses. # `:with` should be used to specify a valid SPDX exception. + # # Add `+` to an identifier to indicate that the formulae can be # licensed under later versions of the same license. - # @see https://docs.brew.sh/License-Guidelines Homebrew License Guidelines - # @see https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/ SPDX license expression guide - #
license "BSD-2-Clause"
- #
license "EPL-1.0+"
- #
license any_of: ["MIT", "GPL-2.0-only"]
- #
license all_of: ["MIT", "GPL-2.0-only"]
- #
license "GPL-2.0-only" => { with: "LLVM-exception" }
- #
license :public_domain
- #
license any_of: [
+    #
+    # ### Examples
+    #
+    # ```ruby
+    # license "BSD-2-Clause"
+    # ```
+    #
+    # ```ruby
+    # license "EPL-1.0+"
+    # ```
+    #
+    # ```ruby
+    # license any_of: ["MIT", "GPL-2.0-only"]
+    # ```
+    #
+    # ```ruby
+    # license all_of: ["MIT", "GPL-2.0-only"]
+    # ```
+    #
+    # ```ruby
+    # license "GPL-2.0-only" => { with: "LLVM-exception" }
+    # ```
+    #
+    # ```ruby
+    # license :public_domain
+    # ```
+    #
+    # ```ruby
+    # license any_of: [
     #   "MIT",
     #   :public_domain,
     #   all_of: ["0BSD", "Zlib", "Artistic-1.0+"],
     #   "Apache-2.0" => { with: "LLVM-exception" },
-    # ]
+ # ] + # ``` # + # @!attribute [w] license + # @see https://docs.brew.sh/License-Guidelines Homebrew License Guidelines + # @see https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/ SPDX license expression guide # @api public def license(args = nil) if args.nil? @@ -3177,14 +3353,26 @@ class Formula end end - # @!attribute [w] allow_network_access! # The phases for which network access is allowed. By default, network # access is allowed for all phases. Valid phases are `:build`, `:test`, # and `:postinstall`. When no argument is passed, network access will be # allowed for all phases. - #
allow_network_access!
- #
allow_network_access! :build
- #
allow_network_access! [:build, :test]
+ # + # ### Examples + # + # ```ruby + # allow_network_access! + # ``` + # + # ```ruby + # allow_network_access! :build + # ``` + # + # ```ruby + # allow_network_access! [:build, :test] + # ``` + # + # @!attribute [w] allow_network_access! sig { params(phases: T.any(Symbol, T::Array[Symbol])).void } def allow_network_access!(phases = []) phases_array = Array(phases) @@ -3199,14 +3387,26 @@ class Formula end end - # @!attribute [w] deny_network_access! # The phases for which network access is denied. By default, network # access is allowed for all phases. Valid phases are `:build`, `:test`, # and `:postinstall`. When no argument is passed, network access will be # denied for all phases. - #
deny_network_access!
- #
deny_network_access! :build
- #
deny_network_access! [:build, :test]
+ # + # ### Examples + # + # ```ruby + # deny_network_access! + # ``` + # + # ```ruby + # deny_network_access! :build + # ``` + # + # ```ruby + # deny_network_access! [:build, :test] + # ``` + # + # @!attribute [w] deny_network_access! sig { params(phases: T.any(Symbol, T::Array[Symbol])).void } def deny_network_access!(phases = []) phases_array = Array(phases) @@ -3230,35 +3430,43 @@ class Formula env_var.nil? ? @network_access_allowed[phase] : env_var == "allow" end - # @!attribute [w] homepage # The homepage for the software. Used by users to get more information # about the software and Homebrew maintainers as a point of contact for # e.g. submitting patches. # Can be opened with running `brew home`. # - #
homepage "https://www.example.com"
+ # ### Example + # + # ```ruby + # homepage "https://www.example.com" + # ``` # # @!attribute [w] homepage # @api public attr_rw :homepage - # Whether a livecheck specification is defined or not. - # It returns true when a livecheck block is present in the {Formula} and - # false otherwise, and is used by livecheck. + # Checks whether a `livecheck` specification is defined or not. + # + # It returns `true` when a `livecheck` block is present in the {Formula} + # and `false` otherwise. sig { returns(T::Boolean) } def livecheckable? @livecheckable == true end - # Whether a service specification is defined or not. - # It returns true when a service block is present in the {Formula} and - # false otherwise, and is used by service. + # Checks whether a service specification is defined or not. + # + # It returns `true` when a service block is present in the {Formula} + # and `false` otherwise. sig { returns(T::Boolean) } def service? @service_block.present? end - attr_reader :conflicts, :skip_clean_paths, :link_overwrite_paths, :pour_bottle_only_if + sig { returns(T::Array[FormulaConflict]) } + attr_reader :conflicts + + attr_reader :skip_clean_paths, :link_overwrite_paths, :pour_bottle_only_if # If `pour_bottle?` returns `false` the user-visible reason to display for # why they cannot use the bottle. @@ -3271,7 +3479,11 @@ class Formula # {Formula} to install a new version linked against the new library version. # `0` if unset. # - #
revision 1
+ # ### Example + # + # ```ruby + # revision 1 + # ``` # # @api public attr_rw :revision @@ -3285,7 +3497,11 @@ class Formula # higher version. # `0` if unset. # - #
version_scheme 1
+ # ### Example + # + # ```ruby + # version_scheme 1 + # ``` # # @api public attr_rw :version_scheme @@ -3301,7 +3517,6 @@ class Formula end.freeze end - # @!attribute [w] url # The URL used to download the source for the {.stable} version of the formula. # We prefer `https` for security and proxy reasons. # If not inferable, specify the download strategy with `using: ...`. @@ -3311,12 +3526,20 @@ class Formula # - `:nounzip` (without extracting) # - `:post` (download via an HTTP POST) # - #
url "https://packed.sources.and.we.prefer.https.example.com/archive-1.2.3.tar.bz2"
- #
url "https://some.dont.provide.archives.example.com",
+    # ### Examples
+    #
+    # ```ruby
+    # url "https://packed.sources.and.we.prefer.https.example.com/archive-1.2.3.tar.bz2"
+    # ```
+    #
+    # ```ruby
+    # url "https://some.dont.provide.archives.example.com",
     #     using:    :git,
     #     tag:      "1.2.3",
-    #     revision: "db8e4de5b2d6653f66aea53094624468caad15d2"
+ # revision: "db8e4de5b2d6653f66aea53094624468caad15d2" + # ``` # + # @!attribute [w] url # @api public def url(val, specs = {}) stable.url(val, specs) @@ -3327,7 +3550,11 @@ class Formula # The version is autodetected from the URL and/or tag so only needs to be # declared if it cannot be autodetected correctly. # - #
version "1.2-final"
+ # ### Example + # + # ```ruby + # version "1.2-final" + # ``` # # @api public def version(val = nil) @@ -3341,8 +3568,12 @@ class Formula # is unreliable. If {.url} is really unreliable then we may swap the # {.mirror} and {.url}. # - #
mirror "https://in.case.the.host.is.down.example.com"
-    # mirror "https://in.case.the.mirror.is.down.example.com
+ # ### Example + # + # ```ruby + # mirror "https://in.case.the.host.is.down.example.com" + # mirror "https://in.case.the.mirror.is.down.example.com + # ``` # # @api public def mirror(val) @@ -3356,14 +3587,17 @@ class Formula # this value you can leave it blank and run `brew fetch --force` and it'll # tell you the currently valid value. # - #
sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7"
+ # ### Example + # + # ```ruby + # sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7" + # ``` # # @api public def sha256(val) stable.sha256(val) end - # @!attribute [w] bottle # Adds a {.bottle} {SoftwareSpec}. # This provides a pre-built binary package built by the Homebrew maintainers for you. # It will be installed automatically if there is a binary package for your platform @@ -3374,14 +3608,16 @@ class Formula # You can ignore this block entirely if submitting to Homebrew/homebrew-core. # It'll be handled for you by the Brew Test Bot. # - #
bottle do
+    # ```ruby
+    # bottle do
     #   root_url "https://example.com" # Optional root to calculate bottle URLs.
     #   rebuild 1 # Marks the old bottle as outdated without bumping the version/revision of the formula.
     #   # Optionally specify the HOMEBREW_CELLAR in which the bottles were built.
     #   sha256 cellar: "/brew/Cellar", catalina:    "ef65c759c5097a36323fa9c77756468649e8d1980a3a4e05695c05e39568967c"
     #   sha256 cellar: :any,           mojave:      "28f4090610946a4eb207df102d841de23ced0d06ba31cb79e040d883906dcd4f"
     #   sha256                         high_sierra: "91dd0caca9bd3f38c439d5a7b6f68440c4274945615fae035ff0a369264b8a2f"
-    # end
+ # end + # ``` # # Homebrew maintainers aim to bottle all formulae. # @@ -3409,13 +3645,17 @@ class Formula # This is required instead of using a conditional. # It is preferable to also pull the {url} and {sha256= sha256} into the block if one is added. # - #
stable do
+    # ### Example
+    #
+    # ```ruby
+    # stable do
     #   url "https://example.com/foo-1.0.tar.gz"
     #   sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7"
     #
     #   depends_on "libxml2"
     #   depends_on "libffi"
-    # end
+ # end + # ``` # # @api public def stable(&block) @@ -3432,10 +3672,22 @@ class Formula # If a block is provided you can also add {.depends_on} and {Patch}es just to the {.head} {SoftwareSpec}. # The download strategies (e.g. `:using =>`) are the same as for {url}. # `master` is the default branch and doesn't need stating with a `branch:` parameter. - #
head "https://we.prefer.https.over.git.example.com/.git"
- #
head "https://example.com/.git", branch: "name_of_branch"
+ # + # ### Example + # + # ```ruby + # head "https://we.prefer.https.over.git.example.com/.git" + # ``` + # + # ```ruby + # head "https://example.com/.git", branch: "name_of_branch" + # ``` + # # or (if autodetect fails): - #
head "https://hg.is.awesome.but.git.has.won.example.com/", using: :hg
+ # + # ```ruby + # head "https://hg.is.awesome.but.git.has.won.example.com/", using: :hg + # ``` def head(val = nil, specs = {}, &block) if block @head.instance_eval(&block) @@ -3449,10 +3701,15 @@ class Formula # Additional downloads can be defined as {resource}s and accessed in the # install method. Resources can also be defined inside a {.stable} or # {.head} block. This mechanism replaces ad-hoc "subformula" classes. - #
resource "additional_files" do
+    #
+    # ### Example
+    #
+    # ```ruby
+    # resource "additional_files" do
     #   url "https://example.com/additional-stuff.tar.gz"
     #   sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
-    # end
+ # end + # ``` # # @api public def resource(name, klass = Resource, &block) @@ -3461,9 +3718,11 @@ class Formula end end + # Specify a Go resource. + # # @api public def go_resource(name, &block) - # odeprecated "Formula#go_resource", "Go modules" + # odeprecated "`Formula.go_resource`", "Go modules" specs.each { |spec| spec.go_resource(name, &block) } end @@ -3472,37 +3731,62 @@ class Formula # that needs extra handling (often changing some ENV vars or # deciding whether to use the system provided version). # + # ### Examples + # # `:build` means this dependency is only needed during build. - #
depends_on "cmake" => :build
+ # + # ```ruby + # depends_on "cmake" => :build + # ``` # # `:test` means this dependency is only needed during testing. - #
depends_on "node" => :test
+ # + # ```ruby + # depends_on "node" => :test + # ``` # # `:recommended` dependencies are built by default. # But a `--without-...` option is generated to opt-out. - #
depends_on "readline" => :recommended
+ # + # ```ruby + # depends_on "readline" => :recommended + # ``` # # `:optional` dependencies are NOT built by default unless the # auto-generated `--with-...` option is passed. - #
depends_on "glib" => :optional
+ # + # ```ruby + # depends_on "glib" => :optional + # ``` # # If you need to specify that another formula has to be built with/out # certain options (note, no `--` needed before the option): - #
depends_on "zeromq" => "with-pgm"
-    # depends_on "qt" => ["with-qtdbus", "developer"] # Multiple options.
+ # + # ```ruby + # depends_on "zeromq" => "with-pgm" + # depends_on "qt" => ["with-qtdbus", "developer"] # Multiple options. + # ``` # # Optional and enforce that "boost" is built using `--with-c++11`. - #
depends_on "boost" => [:optional, "with-c++11"]
+ # + # ```ruby + # depends_on "boost" => [:optional, "with-c++11"] + # ``` # # If a dependency is only needed in certain cases: - #
depends_on "sqlite" if MacOS.version >= :catalina
+    #
+    # ```ruby
+    # depends_on "sqlite" if MacOS.version >= :catalina
     # depends_on xcode: :build # If the formula really needs full Xcode to compile.
     # depends_on macos: :mojave # Needs at least macOS Mojave (10.14) to run.
-    # 
+ # ``` # # It is possible to only depend on something if # `build.with?` or `build.without? "another_formula"`: - #
depends_on "postgresql" if build.without? "sqlite"
+ # + # ```ruby + # depends_on "postgresql" if build.without? "sqlite" + # ``` # # @api public def depends_on(dep) @@ -3536,9 +3820,20 @@ class Formula # # - `:universal`: build a universal binary/library (e.g. on newer Intel Macs # this means a combined x86_64/x86 binary/library). - #
option "with-spam", "The description goes here without a dot at the end"
- #
option "with-qt", "Text here overwrites what's autogenerated by 'depends_on "qt" => :optional'"
- #
option :universal
+ # + # ### Examples + # + # ```ruby + # option "with-spam", "The description goes here without a dot at the end" + # ``` + # + # ```ruby + # option "with-qt", "Text here overwrites what's autogenerated by 'depends_on "qt" => :optional'" + # ``` + # + # ```ruby + # option :universal + # ``` # # @api public def option(name, description = "") @@ -3549,7 +3844,12 @@ class Formula # Deprecated options are used to rename options and migrate users who used # them to newer ones. They are mostly used for migrating non-`with` options # (e.g. `enable-debug`) to `with` options (e.g. `with-debug`). - #
deprecated_option "enable-debug" => "with-debug"
+ # + # ### Example + # + # ```ruby + # deprecated_option "enable-debug" => "with-debug" + # ``` # # @api public def deprecated_option(hash) @@ -3557,44 +3857,66 @@ class Formula end # External patches can be declared using resource-style blocks. - #
patch do
+    #
+    # ### Examples
+    #
+    # ```ruby
+    # patch do
     #   url "https://example.com/example_patch.diff"
     #   sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
-    # end
+ # end + # ``` # # A strip level of `-p1` is assumed. It can be overridden using a symbol # argument: - #
patch :p0 do
+    #
+    # ```ruby
+    # patch :p0 do
     #   url "https://example.com/example_patch.diff"
     #   sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
-    # end
+ # end + # ``` # # Patches can be declared in stable and head blocks. This form is # preferred over using conditionals. - #
stable do
+    #
+    # ```ruby
+    # stable do
     #   patch do
     #     url "https://example.com/example_patch.diff"
     #     sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
     #   end
-    # end
+ # end + # ``` # # Embedded (`__END__`) patches are declared like so: - #
patch :DATA
-    # patch :p0, :DATA
+ # + # ```ruby + # patch :DATA + # patch :p0, :DATA + # ``` # # Patches can also be embedded by passing a string. This makes it possible # to provide multiple embedded patches while making only some of them # conditional. - #
patch :p0, "..."
- # @see https://docs.brew.sh/Formula-Cookbook#patches Patches # + # ```ruby + # patch :p0, "..." + # ``` + # + # @see https://docs.brew.sh/Formula-Cookbook#patches Patches # @api public def patch(strip = :p1, src = nil, &block) specs.each { |spec| spec.patch(strip, src, &block) } end # One or more formulae that conflict with this one and why. - #
conflicts_with "imagemagick", because: "both install `convert` binaries"
+ # + # ### Example + # + # ```ruby + # conflicts_with "imagemagick", because: "both install `convert` binaries" + # ``` # # @api public def conflicts_with(*names) @@ -3605,10 +3927,20 @@ class Formula # Skip cleaning paths in a formula. # # Sometimes the formula {Cleaner cleaner} breaks things. + # + # ### Examples + # # Preserve cleaned paths with: - #
skip_clean "bin/foo", "lib/bar"
+ # + # ```ruby + # skip_clean "bin/foo", "lib/bar" + # ``` + # # Keep .la files with: - #
skip_clean :la
+ # + # ```ruby + # skip_clean :la + # ``` # # @api public def skip_clean(*paths) @@ -3619,15 +3951,26 @@ class Formula # Software that will not be symlinked into the `brew --prefix` and will # only live in its Cellar. Other formulae can depend on it and Homebrew - # will add the necessary includes, libraries, and other paths while + # will add the necessary includes, libraries and other paths while # building that other formula. # # Keg-only formulae are not in your PATH and are not seen by compilers # if you build your own software outside of Homebrew. This way, we # don't shadow software provided by macOS. - #
keg_only :provided_by_macos
- #
keg_only :versioned_formulae
- #
keg_only "because I want it so"
+ # + # ### Examples + # + # ```ruby + # keg_only :provided_by_macos + # ``` + # + # ```ruby + # keg_only :versioned_formulae + # ``` + # + # ```ruby + # keg_only "because I want it so" + # ``` # # @api public def keg_only(reason, explanation = "") @@ -3642,13 +3985,19 @@ class Formula end # Marks the {Formula} as failing with a particular compiler so it will fall back to others. + # + # ### Examples + # # For Apple compilers, this should be in the format: - #
fails_with :clang do
+    #
+    # ```ruby
+    # fails_with :clang do
     #   build 600
     #   cause "multiple configure and compile errors"
-    # end
+ # end + # ``` # - # The block may be omitted, and if present the build may be omitted; + # The block may be omitted and if present, the build may be omitted; # if so, then the compiler will not be allowed for *all* versions. # # `major_version` should be the major release number only, for instance @@ -3659,9 +4008,11 @@ class Formula # For example, if a bug is only triggered on GCC 7.1 but is not # encountered on 7.2: # - #
fails_with :gcc => '7' do
+    # ```ruby
+    # fails_with :gcc => '7' do
     #   version '7.1'
-    # end
+ # end + # ``` # # @api public def fails_with(compiler, &block) @@ -3684,7 +4035,6 @@ class Formula end # A test is required for new formulae and makes us happy. - # @return [Boolean] # # The block will create, run in and delete a temporary directory. # @@ -3694,42 +4044,53 @@ class Formula # and `foo --version` or `foo --help` are bad tests. # However, a bad test is better than no test at all. # - # @see https://docs.brew.sh/Formula-Cookbook#add-a-test-to-the-formula Tests + # ### Examples # - #
(testpath/"test.file").write <<~EOS
+    # ```ruby
+    # (testpath/"test.file").write <<~EOS
     #   writing some test file, if you need to
     # EOS
-    # assert_equal "OK", shell_output("test_command test.file").strip
+ # assert_equal "OK", shell_output("test_command test.file").strip + # ``` # # Need complete control over stdin, stdout? - #
require "open3"
+    #
+    # ```ruby
+    # require "open3"
     # Open3.popen3("#{bin}/example", "argument") do |stdin, stdout, _|
     #   stdin.write("some text")
     #   stdin.close
     #   assert_equal "result", stdout.read
-    # end
+ # end + # ``` # # The test will fail if it returns false, or if an exception is raised. # Failed assertions and failed `system` commands will raise exceptions. # + # @see https://docs.brew.sh/Formula-Cookbook#add-a-test-to-the-formula Tests + # @return [Boolean] # @api public def test(&block) define_method(:test, &block) end - # @!attribute [w] livecheck # {Livecheck} can be used to check for newer versions of the software. # This method evaluates the DSL specified in the livecheck block of the # {Formula} (if it exists) and sets the instance variables of a {Livecheck} # object accordingly. This is used by `brew livecheck` to check for newer # versions of the software. # - #
livecheck do
+    # ### Example
+    #
+    # ```ruby
+    # livecheck do
     #   skip "Not maintained"
     #   url "https://example.com/foo/releases"
     #   regex /foo-(\d+(?:\.\d+)+)\.tar/
-    # end
+ # end + # ``` # + # @!attribute [w] livecheck # @api public def livecheck(&block) return @livecheck unless block @@ -3738,16 +4099,20 @@ class Formula @livecheck.instance_eval(&block) end - # @!attribute [w] service # Service can be used to define services. # This method evaluates the DSL specified in the service block of the # {Formula} (if it exists) and sets the instance variables of a Service # object accordingly. This is used by `brew install` to generate a service file. # - #
service do
-    #   run [opt_bin/"foo"]
-    # end
+ # ### Example # + # ```ruby + # service do + # run [opt_bin/"foo"] + # end + # ``` + # + # @!attribute [w] service # @api public def service(&block) return @service_block unless block @@ -3758,18 +4123,26 @@ class Formula # Defines whether the {Formula}'s bottle can be used on the given Homebrew # installation. # - # For example, if the bottle requires the Xcode CLT to be installed a + # ### Examples + # + # If the bottle requires the Xcode CLT to be installed a # {Formula} would declare: - #
pour_bottle? do
+    #
+    # ```ruby
+    # pour_bottle? do
     #   reason "The bottle needs the Xcode CLT to be installed."
     #   satisfy { MacOS::CLT.installed? }
-    # end
+ # end + # ``` # # If `satisfy` returns `false` then a bottle will not be used and instead # the {Formula} will be built from source and `reason` will be printed. # # Alternatively, a preset reason can be passed as a symbol: - #
pour_bottle? only_if: :clt_installed
+ # + # ```ruby + # pour_bottle? only_if: :clt_installed + # ``` # # @api public def pour_bottle?(only_if: nil, &block) @@ -3811,11 +4184,19 @@ class Formula # Deprecates a {Formula} (on the given date) so a warning is # shown on each installation. If the date has not yet passed the formula # will not be deprecated. - #
deprecate! date: "2020-08-27", because: :unmaintained
- #
deprecate! date: "2020-08-27", because: "has been replaced by foo"
+ # + # ### Examples + # + # ```ruby + # deprecate! date: "2020-08-27", because: :unmaintained + # ``` + # + # ```ruby + # deprecate! date: "2020-08-27", because: "has been replaced by foo" + # ``` + # # @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae # @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS - # # @api public def deprecate!(date:, because:) @deprecation_date = Date.parse(date) @@ -3835,11 +4216,13 @@ class Formula # The date that this {Formula} was or becomes deprecated. # Returns `nil` if no date is specified. + # # @return Date # @see .deprecate! attr_reader :deprecation_date # The reason for deprecation of a {Formula}. + # # @return [nil] if no reason was provided or the formula is not deprecated. # @return [String, Symbol] # @see .deprecate! @@ -3848,11 +4231,19 @@ class Formula # Disables a {Formula} (on the given date) so it cannot be # installed. If the date has not yet passed the formula # will be deprecated instead of disabled. - #
disable! date: "2020-08-27", because: :does_not_build
- #
disable! date: "2020-08-27", because: "has been replaced by foo"
+ # + # ### Examples + # + # ```ruby + # disable! date: "2020-08-27", because: :does_not_build + # ``` + # + # ```ruby + # disable! date: "2020-08-27", because: "has been replaced by foo" + # ``` + # # @see https://docs.brew.sh/Deprecating-Disabling-and-Removing-Formulae # @see DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS - # # @api public def disable!(date:, because:) @disable_date = Date.parse(date) @@ -3869,6 +4260,7 @@ class Formula # Whether this {Formula} is disabled (i.e. cannot be installed). # Defaults to false. + # # @see .disable! sig { returns(T::Boolean) } def disabled? @@ -3877,22 +4269,32 @@ class Formula # The date that this {Formula} was or becomes disabled. # Returns `nil` if no date is specified. + # # @return Date # @see .disable! attr_reader :disable_date # The reason this {Formula} is disabled. # Returns `nil` if no reason was provided or the formula is not disabled. + # # @return [String, Symbol] # @see .disable! attr_reader :disable_reason # Permit overwriting certain files while linking. # - # Sometimes we accidentally install files outside prefix. Once we fix that, + # ### Examples + # + # Sometimes we accidentally install files outside the prefix. Once we fix that, # users will get a link conflict error. Overwrite those files with: - #
link_overwrite "bin/foo", "lib/bar"
- #
link_overwrite "share/man/man1/baz-*"
+ # + # ```ruby + # link_overwrite "bin/foo", "lib/bar" + # ``` + # + # ```ruby + # link_overwrite "share/man/man1/baz-*" + # ``` def link_overwrite(*paths) paths.flatten! link_overwrite_paths.merge(paths) diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb index 838fa97434..77c3a84056 100644 --- a/Library/Homebrew/formula_support.rb +++ b/Library/Homebrew/formula_support.rb @@ -37,7 +37,6 @@ class KegOnlyReason !by_macos? end - # @!visibility private sig { returns(String) } def to_s return @explanation unless @explanation.empty? diff --git a/Library/Homebrew/formula_text_auditor.rb b/Library/Homebrew/formula_text_auditor.rb index 052b811d0b..5600b037bf 100644 --- a/Library/Homebrew/formula_text_auditor.rb +++ b/Library/Homebrew/formula_text_auditor.rb @@ -25,7 +25,6 @@ module Homebrew @text.include? string end - # @!visibility private sig { returns(String) } def to_s @text diff --git a/Library/Homebrew/git_repository.rb b/Library/Homebrew/git_repository.rb index 2f17b2d0f6..5e03a72c1e 100644 --- a/Library/Homebrew/git_repository.rb +++ b/Library/Homebrew/git_repository.rb @@ -106,7 +106,6 @@ class GitRepository popen_git("log", "-1", "--pretty=%B", commit, "--", safe:, err: :out)&.strip end - # @!visibility private sig { returns(String) } def to_s = pathname.to_s diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index f0b8f79623..d1ab5b375a 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -48,7 +48,6 @@ class Keg EOS end - # @!visibility private sig { returns(String) } def to_s s = [] @@ -67,7 +66,6 @@ class Keg # Error for when a directory is not writable. class DirectoryNotWritableError < LinkError - # @!visibility private sig { returns(String) } def to_s <<~EOS @@ -176,11 +174,9 @@ class Keg path.parent end - # @!visibility private sig { returns(String) } def to_s = path.to_s - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}:#{path}>" diff --git a/Library/Homebrew/language/go.rb b/Library/Homebrew/language/go.rb index f66836ae53..c5344e92b2 100644 --- a/Library/Homebrew/language/go.rb +++ b/Library/Homebrew/language/go.rb @@ -14,7 +14,7 @@ module Language # e.g. `resource "github.com/foo/bar"`. sig { params(resources: T::Array[Resource], target: T.any(String, Pathname)).void } def self.stage_deps(resources, target) - # odeprecated "Language::Go::stage_deps", "Go modules" + # odeprecated "`Language::Go.stage_deps`", "Go modules" if resources.empty? if Homebrew::EnvConfig.developer? odie "Tried to stage empty Language::Go resources array" diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb index 71ef9e9bc3..8aaa4c4c0b 100644 --- a/Library/Homebrew/language/python.rb +++ b/Library/Homebrew/language/python.rb @@ -150,8 +150,8 @@ module Language # # @param venv_root [Pathname, String] the path to the root of the virtualenv # (often `libexec/"venv"`) - # @param python [String, Pathname] which interpreter to use (e.g. "python3" - # or "python3.x") + # @param python [String, Pathname] which interpreter to use (e.g. `"python3"` + # or `"python3.x"`) # @param formula [Formula] the active {Formula} # @return [Virtualenv] a {Virtualenv} instance sig { @@ -166,7 +166,7 @@ module Language def virtualenv_create(venv_root, python = "python", formula = T.cast(self, Formula), system_site_packages: true, without_pip: true) # Limit deprecation to 3.12+ for now (or if we can't determine the version). - # Some used this argument for setuptools, which we no longer bundle since 3.12. + # Some used this argument for `setuptools`, which we no longer bundle since 3.12. unless without_pip python_version = Language::Python.major_minor_version(python) if python_version.nil? || python_version.null? || python_version >= "3.12" @@ -198,8 +198,8 @@ module Language # Returns true if a formula option for the specified python is currently # active or if the specified python is required by the formula. Valid - # inputs are "python", "python2", and :python3. Note that - # "with-python", "without-python", "with-python@2", and "without-python@2" + # inputs are `"python"`, `"python2"` and `:python3`. Note that + # `"with-python"`, `"without-python"`, `"with-python@2"` and `"without-python@2"` # formula options are handled correctly even if not associated with any # corresponding depends_on statement. sig { params(python: String).returns(T::Boolean) } diff --git a/Library/Homebrew/lazy_object.rb b/Library/Homebrew/lazy_object.rb index 7f702977ee..364b10f872 100644 --- a/Library/Homebrew/lazy_object.rb +++ b/Library/Homebrew/lazy_object.rb @@ -16,15 +16,20 @@ class LazyObject < Delegator @__delegate__ = @__callable__.call # rubocop:enable Naming/MemoizedInstanceVariableName end + private :__getobj__ def __setobj__(callable) @__callable__ = callable end + private :__setobj__ # Forward to the inner object to make lazy objects type-checkable. + # + # @!visibility private def is_a?(klass) # see https://sorbet.org/docs/faq#how-can-i-fix-type-errors-that-arise-from-super T.bind(self, T.untyped) + __getobj__.is_a?(klass) || super end end diff --git a/Library/Homebrew/livecheck/strategy/extract_plist.rb b/Library/Homebrew/livecheck/strategy/extract_plist.rb index c59d848abd..ba79b24a39 100644 --- a/Library/Homebrew/livecheck/strategy/extract_plist.rb +++ b/Library/Homebrew/livecheck/strategy/extract_plist.rb @@ -39,9 +39,11 @@ module Homebrew ) do extend Forwardable + # @!attribute [r] version # @api public delegate version: :bundle_version + # @!attribute [r] short_version # @api public delegate short_version: :bundle_version end diff --git a/Library/Homebrew/livecheck/strategy/sparkle.rb b/Library/Homebrew/livecheck/strategy/sparkle.rb index c875ec4414..4bae8e669c 100644 --- a/Library/Homebrew/livecheck/strategy/sparkle.rb +++ b/Library/Homebrew/livecheck/strategy/sparkle.rb @@ -54,12 +54,15 @@ module Homebrew ) do extend Forwardable + # @!attribute [r] version # @api public delegate version: :bundle_version + # @!attribute [r] short_version # @api public delegate short_version: :bundle_version + # @!attribute [r] nice_version # @api public delegate nice_version: :bundle_version end diff --git a/Library/Homebrew/locale.rb b/Library/Homebrew/locale.rb index a4c2d5e695..b6cda9a6e7 100644 --- a/Library/Homebrew/locale.rb +++ b/Library/Homebrew/locale.rb @@ -106,7 +106,6 @@ class Locale locale_groups.find { |locales| locales.any? { |locale| include?(locale) } } end - # @!visibility private sig { returns(String) } def to_s [@language, @script, @region].compact.join("-") diff --git a/Library/Homebrew/macos_version.rb b/Library/Homebrew/macos_version.rb index c03c7d46b7..a8ca466404 100644 --- a/Library/Homebrew/macos_version.rb +++ b/Library/Homebrew/macos_version.rb @@ -132,6 +132,7 @@ class MacOSVersion < Version alias requires_popcnt? requires_nehalem_cpu? # Represents the absence of a version. + # # NOTE: Constructor needs to called with an arbitrary macOS-like version which is then set to `nil`. NULL = MacOSVersion.new("10.0").tap { |v| v.instance_variable_set(:@version, nil) }.freeze end @@ -141,7 +142,7 @@ require "lazy_object" module MacOSVersionErrorCompat def const_missing(name) if name == :MacOSVersionError - odisabled "MacOSVersionError", "MacOSVersion::Error" + odisabled "`MacOSVersionError`", "`MacOSVersion::Error`" return MacOSVersion::Error end @@ -158,7 +159,7 @@ end module MacOSVersions SYMBOLS = LazyObject.new do # rubocop:disable Style/MutableConstant - odisabled "MacOSVersions::SYMBOLS", "MacOSVersion::SYMBOLS" + odisabled "`MacOSVersions::SYMBOLS`", "`MacOSVersion::SYMBOLS`" MacOSVersion::SYMBOLS end end @@ -167,7 +168,7 @@ module OS module Mac # TODO: Replace `::Version` with `Version` when this is removed. Version = LazyObject.new do # rubocop:disable Style/MutableConstant - odisabled "OS::Mac::Version", "MacOSVersion" + odisabled "`OS::Mac::Version`", "`MacOSVersion`" MacOSVersion end end diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb index a5465581b3..9da558d5f9 100644 --- a/Library/Homebrew/migrator.rb +++ b/Library/Homebrew/migrator.rb @@ -287,17 +287,18 @@ class Migrator def repin return unless pinned? - # old_pin_record is a relative symlink and when we try to to read it + # `old_pin_record` is a relative symlink and when we try to to read it # from we actually try to find file # /../<...>/../Cellar/name/version. # To repin formula we need to update the link thus that it points to # the right directory. - # NOTE: old_pin_record.realpath.sub(oldname, newname) is unacceptable - # here, because it resolves every symlink for old_pin_record and then + # + # NOTE: `old_pin_record.realpath.sub(oldname, newname)` is unacceptable + # here, because it resolves every symlink for `old_pin_record` and then # substitutes oldname with newname. It breaks things like - # Pathname#make_relative_symlink, where Pathname#relative_path_from - # is used to find relative path from source to destination parent and - # it assumes no symlinks. + # `Pathname#make_relative_symlink`, where `Pathname#relative_path_from` + # is used to find the relative path from source to destination parent + # and it assumes no symlinks. src_oldname = (old_pin_record.dirname/old_pin_link_record).expand_path new_pin_record.make_relative_symlink(src_oldname.sub(oldname, newname)) old_pin_record.delete diff --git a/Library/Homebrew/mktemp.rb b/Library/Homebrew/mktemp.rb index da9e487ba1..4bbf14b5dd 100644 --- a/Library/Homebrew/mktemp.rb +++ b/Library/Homebrew/mktemp.rb @@ -38,7 +38,6 @@ class Mktemp @quiet = true end - # @!visibility private sig { returns(String) } def to_s "[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]" diff --git a/Library/Homebrew/options.rb b/Library/Homebrew/options.rb index 572d615358..6d7d0dfd9d 100644 --- a/Library/Homebrew/options.rb +++ b/Library/Homebrew/options.rb @@ -11,7 +11,6 @@ class Option @description = description end - # @!visibility private sig { returns(String) } def to_s = flag @@ -30,7 +29,6 @@ class Option name.hash end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{flag.inspect}>" @@ -134,13 +132,11 @@ class Options alias to_ary to_a - # @!visibility private sig { returns(String) } def to_s @options.map(&:to_s).join(" ") end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{to_a.inspect}>" diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 5187661442..2f7cceae95 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -51,7 +51,6 @@ class EmbeddedPatch Utils.safe_popen_write("patch", *args) { |p| p.write(data) } end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{strip.inspect}>" @@ -151,7 +150,6 @@ class ExternalPatch raise BuildError.new(f, cmd, args, ENV.to_hash) end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{strip.inspect} #{url.inspect}>" diff --git a/Library/Homebrew/pkg_version.rb b/Library/Homebrew/pkg_version.rb index c72505cc63..b29a52de81 100644 --- a/Library/Homebrew/pkg_version.rb +++ b/Library/Homebrew/pkg_version.rb @@ -39,7 +39,6 @@ class PkgVersion end end - # @!visibility private sig { returns(String) } def to_s = to_str diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb index 038595fd9c..d8df3552e9 100644 --- a/Library/Homebrew/requirement.rb +++ b/Library/Homebrew/requirement.rb @@ -140,7 +140,6 @@ class Requirement [self.class, name, tags].hash end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: #{tags.inspect}>" diff --git a/Library/Homebrew/requirements/arch_requirement.rb b/Library/Homebrew/requirements/arch_requirement.rb index 0f900a162e..9db2d151ca 100644 --- a/Library/Homebrew/requirements/arch_requirement.rb +++ b/Library/Homebrew/requirements/arch_requirement.rb @@ -27,7 +27,6 @@ class ArchRequirement < Requirement "The #{@arch} architecture is required for this software." end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: arch=#{@arch.to_s.inspect} #{tags.inspect}>" diff --git a/Library/Homebrew/requirements/macos_requirement.rb b/Library/Homebrew/requirements/macos_requirement.rb index ac4f9b1b9e..0e7e0cd06e 100644 --- a/Library/Homebrew/requirements/macos_requirement.rb +++ b/Library/Homebrew/requirements/macos_requirement.rb @@ -96,7 +96,6 @@ class MacOSRequirement < Requirement [super, comparator, version].hash end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: version#{@comparator}#{@version.to_s.inspect} #{tags.inspect}>" diff --git a/Library/Homebrew/requirements/xcode_requirement.rb b/Library/Homebrew/requirements/xcode_requirement.rb index 8d4d8c2d1a..0494fd5fae 100644 --- a/Library/Homebrew/requirements/xcode_requirement.rb +++ b/Library/Homebrew/requirements/xcode_requirement.rb @@ -48,7 +48,6 @@ class XcodeRequirement < Requirement end end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}: version>=#{@version.inspect} #{tags.inspect}>" diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 910bc44e11..5f7cc32ad9 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -146,17 +146,22 @@ class Resource < Downloadable super(verify_download_integrity:) end - # @!attribute [w] livecheck # {Livecheck} can be used to check for newer versions of the software. # This method evaluates the DSL specified in the livecheck block of the # {Resource} (if it exists) and sets the instance variables of a {Livecheck} # object accordingly. This is used by `brew livecheck` to check for newer # versions of the software. # - #
livecheck do
+  # ### Example
+  #
+  # ```ruby
+  # livecheck do
   #   url "https://example.com/foo/releases"
   #   regex /foo-(\d+(?:\.\d+)+)\.tar/
-  # end
+ # end + # ``` + # + # @!attribute [w] livecheck def livecheck(&block) return @livecheck unless block @@ -302,7 +307,6 @@ class ResourceStageContext @staging = staging end - # @!visibility private sig { returns(String) } def to_s "<#{self.class}: resource=#{resource} staging=#{staging}>" diff --git a/Library/Homebrew/rubocops/blank.rb b/Library/Homebrew/rubocops/blank.rb index e6a22cb890..b32f1f9412 100644 --- a/Library/Homebrew/rubocops/blank.rb +++ b/Library/Homebrew/rubocops/blank.rb @@ -4,27 +4,26 @@ module RuboCop module Cop module Homebrew - # Checks for code that can be written with simpler conditionals - # using `Object#blank?`. + # Checks for code that can be simplified using `Object#blank?`. # - # @note - # This cop is unsafe autocorrection, because `' '.empty?` returns false, - # but `' '.blank?` returns true. Therefore, autocorrection is not compatible - # if the receiver is a non-empty blank string, tab, or newline meta characters. + # NOTE: Auto-correction for this cop is unsafe because `' '.empty?` returns `false`, + # but `' '.blank?` returns `true`. Therefore, auto-correction is not compatible + # if the receiver is a non-empty blank string. # - # @example - # # Converts usages of `nil? || empty?` to `blank?` + # ### Example # - # # bad - # foo.nil? || foo.empty? - # foo == nil || foo.empty? + # ```ruby + # # bad + # foo.nil? || foo.empty? + # foo == nil || foo.empty? # - # # good - # foo.blank? + # # good + # foo.blank? + # ``` class Blank < Base extend AutoCorrector - MSG_NIL_OR_EMPTY = "Use `%s` instead of `%s`." + MSG = "Use `%s` instead of `%s`." # `(send nil $_)` is not actually a valid match for an offense. Nodes # that have a single method call on the left hand side @@ -49,7 +48,7 @@ module RuboCop nil_or_empty?(node) do |var1, var2| return if var1 != var2 - message = format(MSG_NIL_OR_EMPTY, prefer: replacement(var1), current: node.source) + message = format(MSG, prefer: replacement(var1), current: node.source) add_offense(node, message:) do |corrector| autocorrect(corrector, node) end diff --git a/Library/Homebrew/rubocops/cask/on_system_conditionals.rb b/Library/Homebrew/rubocops/cask/on_system_conditionals.rb index 3039ea9304..d6a267e4ba 100644 --- a/Library/Homebrew/rubocops/cask/on_system_conditionals.rb +++ b/Library/Homebrew/rubocops/cask/on_system_conditionals.rb @@ -9,20 +9,23 @@ module RuboCop module Cask # This cop makes sure that OS conditionals are consistent. # - # @example - # # bad - # cask 'foo' do - # if MacOS.version == :high_sierra - # sha256 "..." - # end - # end + # ### Example # - # # good - # cask 'foo' do - # on_high_sierra do - # sha256 "..." - # end + # ```ruby + # # bad + # cask 'foo' do + # if MacOS.version == :high_sierra + # sha256 "..." # end + # end + # + # # good + # cask 'foo' do + # on_high_sierra do + # sha256 "..." + # end + # end + # ``` class OnSystemConditionals < Base extend Forwardable extend AutoCorrector diff --git a/Library/Homebrew/rubocops/cask/url.rb b/Library/Homebrew/rubocops/cask/url.rb index 49f859310b..e659e9d92c 100644 --- a/Library/Homebrew/rubocops/cask/url.rb +++ b/Library/Homebrew/rubocops/cask/url.rb @@ -6,16 +6,17 @@ module RuboCop module Cask # This cop checks that a cask's `url` stanza is formatted correctly. # - # @example - # # bad - # url "https://example.com/download/foo.dmg", - # verified: "https://example.com/download" + # ### Example # + # ```ruby + # # bad + # url "https://example.com/download/foo.dmg", + # verified: "https://example.com/download" # - # # good - # url "https://example.com/download/foo.dmg", - # verified: "example.com/download/" - # + # # good + # url "https://example.com/download/foo.dmg", + # verified: "example.com/download/" + # ``` class Url < Base extend AutoCorrector extend Forwardable diff --git a/Library/Homebrew/rubocops/cask/variables.rb b/Library/Homebrew/rubocops/cask/variables.rb index 95352ddd22..8a641291f7 100644 --- a/Library/Homebrew/rubocops/cask/variables.rb +++ b/Library/Homebrew/rubocops/cask/variables.rb @@ -8,16 +8,19 @@ module RuboCop module Cask # This cop audits variables in casks. # - # @example - # # bad - # cask do - # arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64" - # end + # ### Example # - # # good - # cask 'foo' do - # arch arm: "darwin-arm64", intel: "darwin" - # end + # ```ruby + # # bad + # cask do + # arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64" + # end + # + # # good + # cask 'foo' do + # arch arm: "darwin-arm64", intel: "darwin" + # end + # ``` class Variables < Base extend Forwardable extend AutoCorrector diff --git a/Library/Homebrew/rubocops/caveats.rb b/Library/Homebrew/rubocops/caveats.rb index 048ddd5bf9..b1a6926606 100644 --- a/Library/Homebrew/rubocops/caveats.rb +++ b/Library/Homebrew/rubocops/caveats.rb @@ -6,27 +6,30 @@ require "rubocops/extend/formula_cop" module RuboCop module Cop module FormulaAudit - # This cop makes sure that caveats don't recommend unsupported or unsafe operations. + # This cop ensures that caveats don't recommend unsupported or unsafe operations. # - # @example - # # bad - # def caveats - # <<~EOS - # Use `setuid` to allow running the exeutable by non-root users. - # EOS - # end + # ### Example # - # # good - # def caveats - # <<~EOS - # Use `sudo` to run the executable. - # EOS - # end + # ```ruby + # # bad + # def caveats + # <<~EOS + # Use `setuid` to allow running the exeutable by non-root users. + # EOS + # end + # + # # good + # def caveats + # <<~EOS + # Use `sudo` to run the executable. + # EOS + # end + # ``` class Caveats < FormulaCop def audit_formula(_node, _class_node, _parent_class_node, _body_node) caveats_strings.each do |n| if regex_match_group(n, /\bsetuid\b/i) - problem "Don't recommend setuid in the caveats, suggest sudo instead." + problem "Don't recommend `setuid` in the caveats, suggest `sudo` instead." end problem "Don't use ANSI escape codes in the caveats." if regex_match_group(n, /\e/) diff --git a/Library/Homebrew/rubocops/compact_blank.rb b/Library/Homebrew/rubocops/compact_blank.rb index 0bdf44159e..167465cfcb 100644 --- a/Library/Homebrew/rubocops/compact_blank.rb +++ b/Library/Homebrew/rubocops/compact_blank.rb @@ -6,43 +6,46 @@ module RuboCop module Homebrew # Checks if collection can be blank-compacted with `compact_blank`. # - # @note - # It is unsafe by default because false positives may occur in the - # blank check of block arguments to the receiver object. + # NOTE: It is unsafe by default because false positives may occur in the + # blank check of block arguments to the receiver object. # - # For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and - # `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`. - # This will work fine when the receiver is a hash object. + # For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and + # `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`. + # This will work fine when the receiver is a hash object. # - # And `compact_blank!` has different implementations for `Array`, `Hash`, and - # `ActionController::Parameters`. - # `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`. - # `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`. - # If the cop makes a mistake, autocorrected code may get unexpected behavior. + # And `compact_blank!` has different implementations for `Array`, `Hash`, and + # `ActionController::Parameters`. + # `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`. + # `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`. + # If the cop makes a mistake, autocorrected code may get unexpected behavior. # - # @example + # ### Examples # - # # bad - # collection.reject(&:blank?) - # collection.reject { |_k, v| v.blank? } + # ```ruby + # # bad + # collection.reject(&:blank?) + # collection.reject { |_k, v| v.blank? } # - # # good - # collection.compact_blank + # # good + # collection.compact_blank + # ``` # - # # bad - # collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` - # collection.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` - # collection.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!` - # collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!` - # - # # good - # collection.compact_blank! + # ```ruby + # # bad + # collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` + # collection.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` + # collection.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!` + # collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!` # + # # good + # collection.compact_blank! + # ``` class CompactBlank < Base include RangeHelp extend AutoCorrector MSG = "Use `%s` instead." + RESTRICT_ON_SEND = [:reject, :delete_if, :reject!].freeze def_node_matcher :reject_with_block?, <<~PATTERN diff --git a/Library/Homebrew/rubocops/homepage.rb b/Library/Homebrew/rubocops/homepage.rb index ccf498c146..e7e2b49c2a 100644 --- a/Library/Homebrew/rubocops/homepage.rb +++ b/Library/Homebrew/rubocops/homepage.rb @@ -70,7 +70,7 @@ module RuboCop # Compact the above into this list as we're able to remove detailed notations, etc over time. when # Check for http:// GitHub homepage URLs, https:// is preferred. - # Note: only check homepages that are repo pages, not *.github.com hosts + # NOTE: Only check homepages that are repo pages, not *.github.com hosts. %r{^http://github\.com/}, %r{^http://[^/]*\.github\.io/}, diff --git a/Library/Homebrew/rubocops/io_read.rb b/Library/Homebrew/rubocops/io_read.rb index 0b58afea01..46ad7e1320 100644 --- a/Library/Homebrew/rubocops/io_read.rb +++ b/Library/Homebrew/rubocops/io_read.rb @@ -4,9 +4,10 @@ module RuboCop module Cop module Homebrew - # This cop restricts usage of IO.read functions for security reasons. + # This cop restricts usage of `IO.read` functions for security reasons. class IORead < Base MSG = "The use of `IO.%s` is a security risk." + RESTRICT_ON_SEND = [:read, :readlines].freeze def on_send(node) diff --git a/Library/Homebrew/rubocops/negate_include.rb b/Library/Homebrew/rubocops/negate_include.rb index ccfec44c7c..ad164c2287 100644 --- a/Library/Homebrew/rubocops/negate_include.rb +++ b/Library/Homebrew/rubocops/negate_include.rb @@ -7,23 +7,25 @@ module RuboCop # Enforces the use of `collection.exclude?(obj)` # over `!collection.include?(obj)`. # - # @note - # This cop is unsafe because false positive will occur for - # receiver objects that do not have an `exclude?` method. (e.g. `IPAddr`) + # NOTE: This cop is unsafe because false positives will occur for + # receiver objects that do not have an `#exclude?` method (e.g. `IPAddr`). # - # @example - # # bad - # !array.include?(2) - # !hash.include?(:key) + # ### Example # - # # good - # array.exclude?(2) - # hash.exclude?(:key) + # ```ruby + # # bad + # !array.include?(2) + # !hash.include?(:key) # + # # good + # array.exclude?(2) + # hash.exclude?(:key) + # ``` class NegateInclude < Base extend AutoCorrector MSG = "Use `.exclude?` and remove the negation part." + RESTRICT_ON_SEND = [:!].freeze def_node_matcher :negate_include_call?, <<~PATTERN diff --git a/Library/Homebrew/rubocops/presence.rb b/Library/Homebrew/rubocops/presence.rb index 97fb8497f9..eddb3afe84 100644 --- a/Library/Homebrew/rubocops/presence.rb +++ b/Library/Homebrew/rubocops/presence.rb @@ -7,37 +7,41 @@ module RuboCop # Checks code that can be written more easily using # `Object#presence` defined by Active Support. # - # @example - # # bad - # a.present? ? a : nil + # ### Examples # - # # bad - # !a.present? ? nil : a + # ```ruby + # # bad + # a.present? ? a : nil # - # # bad - # a.blank? ? nil : a + # # bad + # !a.present? ? nil : a # - # # bad - # !a.blank? ? a : nil + # # bad + # a.blank? ? nil : a # - # # good - # a.presence + # # bad + # !a.blank? ? a : nil # - # @example - # # bad - # a.present? ? a : b + # # good + # a.presence + # ``` # - # # bad - # !a.present? ? b : a + # ```ruby + # # bad + # a.present? ? a : b # - # # bad - # a.blank? ? b : a + # # bad + # !a.present? ? b : a # - # # bad - # !a.blank? ? a : b + # # bad + # a.blank? ? b : a # - # # good - # a.presence || b + # # bad + # !a.blank? ? a : b + # + # # good + # a.presence || b + # ``` class Presence < Base include RangeHelp extend AutoCorrector diff --git a/Library/Homebrew/rubocops/present.rb b/Library/Homebrew/rubocops/present.rb index fb83c69192..80f8ad18cc 100644 --- a/Library/Homebrew/rubocops/present.rb +++ b/Library/Homebrew/rubocops/present.rb @@ -4,24 +4,24 @@ module RuboCop module Cop module Homebrew - # Checks for code that can be written with simpler conditionals - # using `Object#present?`. + # Checks for code that can be simplified using `Object#present?`. # - # @example - # # Converts usages of `!nil? && !empty?` to `present?` + # ### Example # - # # bad - # !foo.nil? && !foo.empty? + # ```ruby + # # bad + # !foo.nil? && !foo.empty? # - # # bad - # foo != nil && !foo.empty? + # # bad + # foo != nil && !foo.empty? # - # # good - # foo.present? + # # good + # foo.present? + # ``` class Present < Base extend AutoCorrector - MSG_EXISTS_AND_NOT_EMPTY = "Use `%s` instead of `%s`." + MSG = "Use `%s` instead of `%s`." def_node_matcher :exists_and_not_empty?, <<~PATTERN (and @@ -41,7 +41,7 @@ module RuboCop exists_and_not_empty?(node) do |var1, var2| return if var1 != var2 - message = format(MSG_EXISTS_AND_NOT_EMPTY, prefer: replacement(var1), current: node.source) + message = format(MSG, prefer: replacement(var1), current: node.source) add_offense(node, message:) do |corrector| autocorrect(corrector, node) @@ -53,7 +53,7 @@ module RuboCop exists_and_not_empty?(node) do |var1, var2| return if var1 != var2 - add_offense(node, message: MSG_EXISTS_AND_NOT_EMPTY) do |corrector| + add_offense(node, message: MSG) do |corrector| autocorrect(corrector, node) end end diff --git a/Library/Homebrew/rubocops/safe_navigation_with_blank.rb b/Library/Homebrew/rubocops/safe_navigation_with_blank.rb index 4e104d2d5e..8862da6d58 100644 --- a/Library/Homebrew/rubocops/safe_navigation_with_blank.rb +++ b/Library/Homebrew/rubocops/safe_navigation_with_blank.rb @@ -7,28 +7,26 @@ module RuboCop # Checks to make sure safe navigation isn't used with `blank?` in # a conditional. # - # @note - # While the safe navigation operator is generally a good idea, when - # checking `foo&.blank?` in a conditional, `foo` being `nil` will actually - # do the opposite of what the author intends. + # NOTE: While the safe navigation operator is generally a good idea, when + # checking `foo&.blank?` in a conditional, `foo` being `nil` will actually + # do the opposite of what the author intends: # - # For example: + # ```ruby + # foo&.blank? #=> nil + # foo.blank? #=> true + # ``` # - # [source,ruby] - # ---- - # foo&.blank? #=> nil - # foo.blank? #=> true - # ---- + # ### Example # - # @example - # # bad - # do_something if foo&.blank? - # do_something unless foo&.blank? - # - # # good - # do_something if foo.blank? - # do_something unless foo.blank? + # ```ruby + # # bad + # do_something if foo&.blank? + # do_something unless foo&.blank? # + # # good + # do_something if foo.blank? + # do_something unless foo.blank? + # ``` class SafeNavigationWithBlank < Base extend AutoCorrector diff --git a/Library/Homebrew/rubocops/service.rb b/Library/Homebrew/rubocops/service.rb index a141e6fc74..e63a0a9917 100644 --- a/Library/Homebrew/rubocops/service.rb +++ b/Library/Homebrew/rubocops/service.rb @@ -30,7 +30,7 @@ module RuboCop method_calls.delete(:service) # NOTE: Solving the first problem here might solve the second one too - # so we don't show both of them at the same time. + # so we don't show both of them at the same time. if !method_calls.keys.intersect?(REQUIRED_METHOD_CALLS) offending_node(service_node) problem "Service blocks require `run` or `name` to be defined." diff --git a/Library/Homebrew/rubocops/shared/helper_functions.rb b/Library/Homebrew/rubocops/shared/helper_functions.rb index 4a62e02b2f..7e6d9f6601 100644 --- a/Library/Homebrew/rubocops/shared/helper_functions.rb +++ b/Library/Homebrew/rubocops/shared/helper_functions.rb @@ -174,10 +174,19 @@ module RuboCop # Matches a method with a receiver. Yields to a block with matching method node. # - # @example to match `Formula.factory(name)` - # find_instance_method_call(node, "Formula", :factory) - # @example to match `build.head?` - # find_instance_method_call(node, :build, :head?) + # ### Examples + # + # Match `Formula.factory(name)`. + # + # ```ruby + # find_instance_method_call(node, "Formula", :factory) + # ``` + # + # Match `build.head?`. + # + # ```ruby + # find_instance_method_call(node, :build, :head?) + # ``` def find_instance_method_call(node, instance, method_name) methods = find_every_method_call_by_name(node, method_name) methods.each do |method| @@ -194,8 +203,13 @@ module RuboCop # Matches receiver part of method. Yields to a block with parent node of receiver. # - # @example to match `ARGV.()` - # find_instance_call(node, "ARGV") + # ### Example + # + # Match `ARGV.()`. + # + # ```ruby + # find_instance_call(node, "ARGV") + # ``` def find_instance_call(node, name) node.each_descendant(:send) do |method_node| next if method_node.receiver.nil? diff --git a/Library/Homebrew/rubocops/shell_commands.rb b/Library/Homebrew/rubocops/shell_commands.rb index 537c1be798..4d0dac7f7f 100644 --- a/Library/Homebrew/rubocops/shell_commands.rb +++ b/Library/Homebrew/rubocops/shell_commands.rb @@ -40,9 +40,11 @@ module RuboCop until while ].freeze + private_constant :SHELL_BUILTINS # https://github.com/ruby/ruby/blob/v2_6_3/process.c#L2495 SHELL_METACHARACTERS = %W[* ? { } [ ] < > ( ) ~ & | \\ $ ; ' ` " \n #].freeze + private_constant :SHELL_METACHARACTERS # This cop makes sure that shell command arguments are separated. class ShellCommands < Base @@ -60,6 +62,8 @@ module RuboCop [:Utils, :popen_write], [:Utils, :safe_popen_write], ].freeze + private_constant :TARGET_METHODS + RESTRICT_ON_SEND = TARGET_METHODS.map(&:second).uniq.freeze def on_send(node) diff --git a/Library/Homebrew/rubocops/urls.rb b/Library/Homebrew/rubocops/urls.rb index 4e388166c2..c825d00398 100644 --- a/Library/Homebrew/rubocops/urls.rb +++ b/Library/Homebrew/rubocops/urls.rb @@ -207,7 +207,7 @@ module RuboCop problem "Use versioned rather than branch tarballs for stable checksums." end - # Use new-style archive downloads + # Use new-style archive downloads. archive_gh_pattern = %r{https://.*github.*/(?:tar|zip)ball/} audit_urls(urls, archive_gh_pattern) do |_, url| next if url.end_with?(".git") diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 96d7e49333..3f3beb38a4 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -138,7 +138,7 @@ class SoftwareSpec end def go_resource(name, &block) - # odeprecated "SoftwareSpec#go_resource", "Go modules" + # odeprecated "`SoftwareSpec#go_resource`", "Go modules" resource name, Resource::Go, &block end @@ -207,18 +207,6 @@ class SoftwareSpec depends_on UsesFromMacOSDependency.new(dep, tags, bounds:) end - # @deprecated - def uses_from_macos_elements - # TODO: Remember to remove the delegate from `Formula`. - odisabled "#uses_from_macos_elements", "#declared_deps" - end - - # @deprecated - def uses_from_macos_names - # TODO: Remember to remove the delegate from `Formula`. - odisabled "#uses_from_macos_names", "#declared_deps" - end - def deps dependency_collector.deps.dup_without_system_deps end @@ -318,7 +306,6 @@ class Bottle "#{name}--#{version}#{extname}" end - # @!visibility private sig { returns(String) } def to_s = to_str diff --git a/Library/Homebrew/sorbet/rbi/parlour.rbi b/Library/Homebrew/sorbet/rbi/parlour.rbi index 8514d0cca0..aee33eadc2 100644 --- a/Library/Homebrew/sorbet/rbi/parlour.rbi +++ b/Library/Homebrew/sorbet/rbi/parlour.rbi @@ -80,21 +80,12 @@ class Formula sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T::Boolean) } def loaded_from_api?(*args, **options, &block); end - sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } - def resource(*args, **options, &block); end - sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } def deps(*args, **options, &block); end sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } def declared_deps(*args, **options, &block); end - sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } - def uses_from_macos_elements(*args, **options, &block); end - - sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } - def uses_from_macos_names(*args, **options, &block); end - sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } def requirements(*args, **options, &block); end @@ -161,9 +152,6 @@ class Formula sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } def env(*args, **options, &block); end - sig { params(args: T.untyped, options: T.untyped, block: T.untyped).returns(T.untyped) } - def conflicts(*args, **options, &block); end - sig { returns(T::Boolean) } def self.loaded_from_api?; end diff --git a/Library/Homebrew/source_location.rb b/Library/Homebrew/source_location.rb index a75cc443c0..b3671cb5a4 100644 --- a/Library/Homebrew/source_location.rb +++ b/Library/Homebrew/source_location.rb @@ -16,7 +16,6 @@ module Homebrew @column = column end - # @!visibility private sig { returns(String) } def to_s "#{line}#{column&.to_s&.prepend(":")}" diff --git a/Library/Homebrew/style.rb b/Library/Homebrew/style.rb index 426fc91312..066438b32e 100644 --- a/Library/Homebrew/style.rb +++ b/Library/Homebrew/style.rb @@ -179,7 +179,7 @@ module Homebrew # -f (--force) : we know what we are doing, force apply patches # -d / (--directory=/) : change to root directory, since we use absolute file paths # -p0 (--strip=0) : do not strip path prefixes, since we are at root directory - # NOTE: we use short flags where for compatibility + # NOTE: We use short flags for compatibility. patch_command = %w[patch -g 0 -f -d / -p0] patches = system_command(shellcheck, args: ["--format=diff", *args]).stdout Utils.safe_popen_write(*patch_command) { |p| p.write(patches) } if patches.present? diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index f55da44815..163e9182ea 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -13,12 +13,18 @@ class Tab FILENAME = "INSTALL_RECEIPT.json" + # Check whether the formula was installed as a dependency. + # # @api internal attr_accessor :installed_as_dependency + # Check whether the formula was installed on request. + # # @api internal attr_accessor :installed_on_request + # Check whether the formula was poured from a bottle. + # # @api internal attr_accessor :poured_from_bottle @@ -27,6 +33,8 @@ class Tab :built_on attr_writer :used_options, :unused_options, :compiler, :source_modified_time + # Returns the formula's runtime dependencies. + # # @api internal attr_writer :runtime_dependencies @@ -72,7 +80,8 @@ class Tab end # Returns the {Tab} for an install receipt at `path`. - # Results are cached. + # + # NOTE: Results are cached. def self.from_file(path) cache.fetch(path) do |p| content = File.read(p) @@ -282,7 +291,10 @@ class Tab spec == :stable end + # The options used to install the formula. + # # @api internal + sig { returns(Options) } def used_options Options.create(@used_options) end @@ -321,6 +333,7 @@ class Tab built_as_bottle end + sig { returns(T.nilable(Tap)) } def tap tap_name = source["tap"] Tap.fetch(tap_name) if tap_name @@ -407,7 +420,6 @@ class Tab tabfile.atomic_write(to_json) end - # @!visibility private sig { returns(String) } def to_s s = [] diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index dd97163a59..82d24e4d74 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -154,7 +154,6 @@ class Tap attr_reader :name # @api public - # @!visibility private sig { returns(String) } def to_s = name diff --git a/Library/Homebrew/test/ENV_spec.rb b/Library/Homebrew/test/ENV_spec.rb index c5417db549..78649f3e83 100644 --- a/Library/Homebrew/test/ENV_spec.rb +++ b/Library/Homebrew/test/ENV_spec.rb @@ -73,8 +73,8 @@ RSpec.describe "ENV" do expect(subject["foo"]).to eq("1") end - # NOTE: this may be a wrong behavior; we should probably reject objects that - # do not respond to #to_str. For now this documents existing behavior. + # NOTE: This may be a wrong behavior; we should probably reject objects that + # do not respond to `#to_str`. For now this documents existing behavior. it "coerces a value to a string" do subject.append "foo", 42 expect(subject["foo"]).to eq("42") diff --git a/Library/Homebrew/test/cask/cask_spec.rb b/Library/Homebrew/test/cask/cask_spec.rb index 9553e2510e..701a58a204 100644 --- a/Library/Homebrew/test/cask/cask_spec.rb +++ b/Library/Homebrew/test/cask/cask_spec.rb @@ -332,8 +332,8 @@ RSpec.describe Cask::Cask, :cask do expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip end - # @note The calls to `Cask.generating_hash!` and `Cask.generated_hash!` - # are not idempotent so they can only be used in one test. + # NOTE: The calls to `Cask.generating_hash!` and `Cask.generated_hash!` + # are not idempotent so they can only be used in one test. it "returns the correct hash placeholders" do described_class.generating_hash! expect(described_class).to be_generating_hash diff --git a/Library/Homebrew/test/caveats_spec.rb b/Library/Homebrew/test/caveats_spec.rb index 58b41f24f9..97c2970ded 100644 --- a/Library/Homebrew/test/caveats_spec.rb +++ b/Library/Homebrew/test/caveats_spec.rb @@ -87,7 +87,7 @@ RSpec.describe Caveats do expect(caveats).to include("tmux") end - # @todo This should get deprecated and the service block `plist_name` method should get used instead. + # TODO: This should get deprecated and the service block `plist_name` method should get used instead. it "prints info when there are custom service files" do f = formula do url "foo-1.0" diff --git a/Library/Homebrew/test/livecheck/strategy/electron_builder_spec.rb b/Library/Homebrew/test/livecheck/strategy/electron_builder_spec.rb index fde044cb4f..24143c280e 100644 --- a/Library/Homebrew/test/livecheck/strategy/electron_builder_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/electron_builder_spec.rb @@ -79,9 +79,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::ElectronBuilder do end).to eq(find_versions_cached_return_hash.merge({ regex: })) # NOTE: A regex should be provided using the `#regex` method in a - # `livecheck` block but we're using a regex literal in the `strategy` - # block here simply to ensure this method works as expected when a - # regex isn't provided. + # `livecheck` block but we're using a regex literal in the `strategy` + # block here simply to ensure this method works as expected when a + # regex isn't provided. expect(electron_builder.find_versions(url: http_url, provided_content: content) do |yaml| regex = /^v?(\d+(?:\.\d+)+)$/i yaml["version"][regex, 1] diff --git a/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb b/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb index d7baece1eb..39553a28d0 100644 --- a/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb @@ -75,7 +75,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::HeaderMatch do end it "returns an array of version strings when given headers and a block" do - # Returning a string from block, no regex + # Returning a string from block, no regex. expect( header_match.versions_from_headers(headers[:location]) do |headers| v = Version.parse(headers["location"], detected_from_url: true) @@ -83,16 +83,17 @@ RSpec.describe Homebrew::Livecheck::Strategy::HeaderMatch do end, ).to eq(versions[:location]) - # Returning a string from block, explicit regex + # Returning a string from block, explicit regex. expect( header_match.versions_from_headers(headers[:location], regexes[:latest]) do |headers, regex| headers["location"] ? headers["location"][regex, 1] : nil end, ).to eq(versions[:location]) - # Returning an array of strings from block - # NOTE: Strategies runs `#compact` on an array from a block, so nil - # values are filtered out without needing to use `#compact` in the block. + # Returning an array of strings from block. + # + # NOTE: Strategies runs `#compact` on an array from a block, so nil values + # are filtered out without needing to use `#compact` in the block. expect( header_match.versions_from_headers( headers[:content_disposition_and_location], diff --git a/Library/Homebrew/test/livecheck/strategy/json_spec.rb b/Library/Homebrew/test/livecheck/strategy/json_spec.rb index 43c47250f5..dc18a8f074 100644 --- a/Library/Homebrew/test/livecheck/strategy/json_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/json_spec.rb @@ -126,9 +126,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::Json do end).to eq(find_versions_cached_return_hash) # NOTE: A regex should be provided using the `#regex` method in a - # `livecheck` block but we're using a regex literal in the `strategy` - # block here simply to ensure this method works as expected when a - # regex isn't provided. + # `livecheck` block but we're using a regex literal in the `strategy` + # block here simply to ensure this method works as expected when a + # regex isn't provided. expect(json.find_versions(url: http_url, provided_content: content) do |json| regex = /^v?(\d+(?:\.\d+)+)$/i json["versions"].select { |item| item["version"]&.match?(regex) } diff --git a/Library/Homebrew/test/livecheck/strategy/page_match_spec.rb b/Library/Homebrew/test/livecheck/strategy/page_match_spec.rb index 4b2fab9321..6c79eaf646 100644 --- a/Library/Homebrew/test/livecheck/strategy/page_match_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/page_match_spec.rb @@ -109,11 +109,11 @@ RSpec.describe Homebrew::Livecheck::Strategy::PageMatch do .to eq(find_versions_cached_return_hash) # NOTE: Ideally, a regex should always be provided to `#find_versions` - # for `PageMatch` but there are currently some `livecheck` blocks in - # casks where `#regex` isn't used and the regex only exists within a - # `strategy` block. This isn't ideal but, for the moment, we allow a - # `strategy` block to act as a substitution for a regex and we need to - # test this scenario to ensure it works. + # for `PageMatch` but there are currently some `livecheck` blocks in + # casks where `#regex` isn't used and the regex only exists within a + # `strategy` block. This isn't ideal but, for the moment, we allow a + # `strategy` block to act as a substitution for a regex and we need to + # test this scenario to ensure it works. # # Under normal circumstances, a regex should be established in a # `livecheck` block using `#regex` and passed into the `strategy` block diff --git a/Library/Homebrew/test/livecheck/strategy/xml_spec.rb b/Library/Homebrew/test/livecheck/strategy/xml_spec.rb index b879049556..39c93075cd 100644 --- a/Library/Homebrew/test/livecheck/strategy/xml_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/xml_spec.rb @@ -218,9 +218,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::Xml do end).to eq(find_versions_cached_return_hash) # NOTE: A regex should be provided using the `#regex` method in a - # `livecheck` block but we're using a regex literal in the `strategy` - # block here simply to ensure this method works as expected when a - # regex isn't provided. + # `livecheck` block but we're using a regex literal in the `strategy` + # block here simply to ensure this method works as expected when a + # regex isn't provided. expect(xml.find_versions(url: http_url, provided_content: content_version_text) do |xml| regex = /^v?(\d+(?:\.\d+)+)$/i xml.get_elements("/versions/version").map { |item| item.text[regex, 1] } diff --git a/Library/Homebrew/test/livecheck/strategy/yaml_spec.rb b/Library/Homebrew/test/livecheck/strategy/yaml_spec.rb index 72d7a67f36..8d2f3827f9 100644 --- a/Library/Homebrew/test/livecheck/strategy/yaml_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/yaml_spec.rb @@ -127,9 +127,9 @@ RSpec.describe Homebrew::Livecheck::Strategy::Yaml do end).to eq(find_versions_cached_return_hash) # NOTE: A regex should be provided using the `#regex` method in a - # `livecheck` block but we're using a regex literal in the `strategy` - # block here simply to ensure this method works as expected when a - # regex isn't provided. + # `livecheck` block but we're using a regex literal in the `strategy` + # block here simply to ensure this method works as expected when a + # regex isn't provided. expect(yaml.find_versions(url: http_url, provided_content: content) do |yaml| regex = /^v?(\d+(?:\.\d+)+)$/i yaml["versions"].select { |item| item["version"]&.match?(regex) } diff --git a/Library/Homebrew/test/service_spec.rb b/Library/Homebrew/test/service_spec.rb index 7b0c43cebb..a4b7a913a9 100644 --- a/Library/Homebrew/test/service_spec.rb +++ b/Library/Homebrew/test/service_spec.rb @@ -1058,8 +1058,8 @@ RSpec.describe Homebrew::Service do } end - # @note The calls to `Formula.generating_hash!` and `Formula.generated_hash!` - # are not idempotent so they can only be used in one test. + # NOTE: The calls to `Formula.generating_hash!` and `Formula.generated_hash!` + # are not idempotent so they can only be used in one test. it "replaces local paths with placeholders" do f = stub_formula do service do diff --git a/Library/Homebrew/test/sorbet/tapioca/compilers/args_spec.rb b/Library/Homebrew/test/sorbet/tapioca/compilers/args_spec.rb index c160203735..ebb2716fde 100644 --- a/Library/Homebrew/test/sorbet/tapioca/compilers/args_spec.rb +++ b/Library/Homebrew/test/sorbet/tapioca/compilers/args_spec.rb @@ -10,7 +10,7 @@ RSpec.describe Tapioca::Compilers::Args do Homebrew::Cmd::List.parser end - # good testing candidate, bc it has multiple for each of switch, flag, and comma_array args: + # Good testing candidate because it has multiple for each of `switch`, `flag` and `comma_array` args: let(:update_python_resources_parser) do require "dev-cmd/update-python-resources" Homebrew::DevCmd::UpdatePythonResources.parser diff --git a/Library/Homebrew/test/support/extend/cachable.rb b/Library/Homebrew/test/support/extend/cachable.rb index 764314674d..748b0f7ed4 100644 --- a/Library/Homebrew/test/support/extend/cachable.rb +++ b/Library/Homebrew/test/support/extend/cachable.rb @@ -35,8 +35,8 @@ module Cachable # A list of all classes that have been loaded into memory that mixin or # inherit `Cachable` at the class or module level. # - # Note: Classes that inherit from `Formula` are excluded since it's not - # necessary to track and clear individual formula caches. + # NOTE: Classes that inherit from `Formula` are excluded since it's not + # necessary to track and clear individual formula caches. def self.class_list @class_list ||= [] end @@ -44,8 +44,8 @@ module Cachable # Clear the cache of every class or module that mixes in or inherits # `Cachable` at the class or module level. # - # Note: Classes that inherit from `Formula` are excluded since it's not - # necessary to track and clear individual formula caches. + # NOTE: Classes that inherit from `Formula` are excluded since it's not + # necessary to track and clear individual formula caches. def self.clear_all_caches class_list.each(&:clear_cache) end diff --git a/Library/Homebrew/test/unpack_strategy/zstd_spec.rb b/Library/Homebrew/test/unpack_strategy/zstd_spec.rb index 2fe9b40f16..b439ed657f 100644 --- a/Library/Homebrew/test/unpack_strategy/zstd_spec.rb +++ b/Library/Homebrew/test/unpack_strategy/zstd_spec.rb @@ -6,11 +6,11 @@ RSpec.describe UnpackStrategy::Zstd do let(:path) { TEST_FIXTURE_DIR/"cask/container.tar.zst" } it "is correctly detected" do - # UnpackStrategy.detect(path) for a .tar.XXX file returns either UnpackStrategy::Tar if - # the host's tar is able to extract that compressed file or UnpackStrategy::XXX otherwise, - # such as UnpackStrategy::Zstd. On macOS UnpackStrategy.detect("container.tar.zst") - # returns UnpackStrategy::Zstd, and on ubuntu-22.04 it returns UnpackStrategy::Tar, - # because the host's version of tar is recent enough and zstd is installed. + # `UnpackStrategy.detect(path)` for a `.tar.XXX` file returns either `UnpackStrategy::Tar` if + # the host's `tar` is able to extract that compressed file or `UnpackStrategy::XXX` otherwise, + # such as `UnpackStrategy::Zstd`. On macOS `UnpackStrategy.detect("container.tar.zst")` + # returns `UnpackStrategy::Zstd` and on Ubuntu 22.04 it returns `UnpackStrategy::Tar`, + # because the host's version of `tar` is recent enough and `zstd` is installed. expect(UnpackStrategy.detect(path)).to(be_a(described_class).or(be_a(UnpackStrategy::Tar))) end end diff --git a/Library/Homebrew/test/utils/shell_spec.rb b/Library/Homebrew/test/utils/shell_spec.rb index b5f8d9b6d6..f3f2fb9bce 100644 --- a/Library/Homebrew/test/utils/shell_spec.rb +++ b/Library/Homebrew/test/utils/shell_spec.rb @@ -72,7 +72,7 @@ RSpec.describe Utils::Shell do specify "::csh_quote" do expect(described_class.send(:csh_quote, "")).to eq("''") expect(described_class.send(:csh_quote, "\\")).to eq("\\\\") - # NOTE: this test is different than for sh + # NOTE: This test is different than for `sh`. expect(described_class.send(:csh_quote, "\n")).to eq("'\\\n'") expect(described_class.send(:csh_quote, "$")).to eq("\\$") expect(described_class.send(:csh_quote, "word")).to eq("word") diff --git a/Library/Homebrew/url.rb b/Library/Homebrew/url.rb index e9fcb2b377..adbff352fc 100644 --- a/Library/Homebrew/url.rb +++ b/Library/Homebrew/url.rb @@ -15,7 +15,6 @@ class URL @specs.freeze end - # @!visibility private sig { returns(String) } def to_s @url diff --git a/Library/Homebrew/utils/bottles.rb b/Library/Homebrew/utils/bottles.rb index 1518299a96..34ce838f85 100644 --- a/Library/Homebrew/utils/bottles.rb +++ b/Library/Homebrew/utils/bottles.rb @@ -202,7 +202,6 @@ module Utils end end - # @!visibility private sig { returns(String) } def to_s to_sym.to_s diff --git a/Library/Homebrew/utils/gems.rb b/Library/Homebrew/utils/gems.rb index 824c238fd2..756bb8808e 100644 --- a/Library/Homebrew/utils/gems.rb +++ b/Library/Homebrew/utils/gems.rb @@ -239,7 +239,7 @@ module Homebrew install_bundler! - # Combine the passed groups with the ones stored in settings + # Combine the passed groups with the ones stored in settings. groups |= (user_gem_groups & valid_gem_groups) groups.sort! diff --git a/Library/Homebrew/utils/github/actions.rb b/Library/Homebrew/utils/github/actions.rb index 412884d976..9e20bef10b 100644 --- a/Library/Homebrew/utils/github/actions.rb +++ b/Library/Homebrew/utils/github/actions.rb @@ -73,7 +73,6 @@ module GitHub @end_column = Integer(end_column) if end_column end - # @!visibility private sig { returns(String) } def to_s metadata = @type.to_s diff --git a/Library/Homebrew/utils/inreplace.rb b/Library/Homebrew/utils/inreplace.rb index 4031fa9c2d..6f866382c4 100644 --- a/Library/Homebrew/utils/inreplace.rb +++ b/Library/Homebrew/utils/inreplace.rb @@ -23,13 +23,21 @@ module Utils # defined by the formula, as only `HOMEBREW_PREFIX` is available # in the {DATAPatch embedded patch}. # - # @example `inreplace` supports regular expressions: - # inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool" + # ### Examples # - # @example `inreplace` supports blocks: - # inreplace "Makefile" do |s| - # s.gsub! "/usr/local", HOMEBREW_PREFIX.to_s - # end + # `inreplace` supports regular expressions: + # + # ```ruby + # inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool" + # ``` + # + # `inreplace` supports blocks: + # + # ```ruby + # inreplace "Makefile" do |s| + # s.gsub! "/usr/local", HOMEBREW_PREFIX.to_s + # end + # ``` # # @see StringInreplaceExtension # @api public diff --git a/Library/Homebrew/utils/pypi.rb b/Library/Homebrew/utils/pypi.rb index ac7da48422..d6a6102bd8 100644 --- a/Library/Homebrew/utils/pypi.rb +++ b/Library/Homebrew/utils/pypi.rb @@ -82,7 +82,6 @@ module PyPI ] end - # @!visibility private sig { returns(String) } def to_s if valid_pypi_package? diff --git a/Library/Homebrew/utils/shebang.rb b/Library/Homebrew/utils/shebang.rb index 34d2356672..3a5d784b1f 100644 --- a/Library/Homebrew/utils/shebang.rb +++ b/Library/Homebrew/utils/shebang.rb @@ -20,8 +20,11 @@ module Utils # Rewrite shebang for the given `paths` using the given `rewrite_info`. # - # @example - # rewrite_shebang detected_python_shebang, bin/"script.py" + # ### Example + # + # ```ruby + # rewrite_shebang detected_python_shebang, bin/"script.py" + # ``` # # @api public sig { params(rewrite_info: RewriteInfo, paths: T.any(String, Pathname)).void } diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index c6b3bd8877..637a90e6d3 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -98,7 +98,6 @@ module Tty end end - # @!visibility private sig { returns(String) } def to_s return "" unless color? diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index f42dbeddb4..e6e8dac8d0 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -57,7 +57,6 @@ class Version sig { abstract.params(other: T.untyped).returns(T.nilable(Integer)) } def <=>(other); end - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name} #{value.inspect}>" @@ -83,7 +82,6 @@ class Version value.to_s end - # @!visibility private sig { returns(String) } def to_s = to_str @@ -135,7 +133,6 @@ class Version sig { returns(T::Boolean) } def blank? = true - # @!visibility private sig { returns(String) } def inspect "#<#{self.class.name}>" @@ -350,7 +347,7 @@ class Version sig { params(val: String).returns(Version) } def self.create(val) - odisabled "Version.create", "Version.new" + odisabled "`Version.create`", "`Version.new`" new(val) end @@ -516,12 +513,16 @@ class Version private_constant :HEAD_VERSION_REGEX # Check if this is a HEAD version. + # + # @api public sig { returns(T::Boolean) } def head? version&.match?(HEAD_VERSION_REGEX) || false end # Return the commit for a HEAD version. + # + # @api public sig { returns(T.nilable(String)) } def commit version&.match(HEAD_VERSION_REGEX)&.[](:commit) @@ -646,6 +647,8 @@ class Version end alias eql? == + # The major version. + # # @api public sig { returns(T.nilable(Token)) } def major @@ -654,6 +657,8 @@ class Version tokens.first end + # The minor version. + # # @api public sig { returns(T.nilable(Token)) } def minor @@ -662,6 +667,8 @@ class Version tokens.second end + # The patch version. + # # @api public sig { returns(T.nilable(Token)) } def patch @@ -670,6 +677,8 @@ class Version tokens.third end + # The major and minor version. + # # @api public sig { returns(T.self_type) } def major_minor @@ -679,6 +688,8 @@ class Version major_minor.empty? ? NULL : self.class.new(major_minor.join(".")) end + # The major, minor and patch version. + # # @api public sig { returns(T.self_type) } def major_minor_patch @@ -693,6 +704,9 @@ class Version version.hash end + # Convert the version to a floating-point number. + # + # @api public sig { returns(Float) } def to_f return Float::NAN if null? @@ -700,11 +714,15 @@ class Version version.to_f end + # Convert the version to an integer. + # + # @api public sig { returns(Integer) } def to_i version.to_i end + # @api public sig { returns(String) } def to_str raise NoMethodError, "undefined method `to_str' for #{self.class}:NULL" if null? @@ -712,7 +730,7 @@ class Version T.must(version).to_str end - # @!visibility private + # @api public sig { returns(String) } def to_s = version.to_s @@ -728,7 +746,6 @@ class Version super end - # @!visibility private sig { returns(String) } def inspect return "#" if null? @@ -760,6 +777,7 @@ class Version end # Represents the absence of a version. + # # NOTE: Constructor needs to called with an arbitrary non-empty version which is then set to `nil`. NULL = Version.new("NULL").tap { |v| v.instance_variable_set(:@version, nil) }.freeze end diff --git a/Library/Homebrew/yard/docstring_parser.rb b/Library/Homebrew/yard/docstring_parser.rb index 739916fbfd..41770c4102 100644 --- a/Library/Homebrew/yard/docstring_parser.rb +++ b/Library/Homebrew/yard/docstring_parser.rb @@ -5,15 +5,90 @@ module Homebrew module YARD class DocstringParser < ::YARD::DocstringParser + # Every `Object` has these methods. + OVERRIDABLE_METHODS = [ + :hash, :inspect, :to_s, + :<=>, :===, :!~, :eql?, :equal?, :!, :==, :!= + ].freeze + private_constant :OVERRIDABLE_METHODS + + SELF_EXPLANATORY_METHODS = [:to_yaml, :to_json, :to_str].freeze + private_constant :SELF_EXPLANATORY_METHODS + def parse_content(content) + # Convert plain text to tags. + content = content&.gsub(/^\s*(TODO|FIXME):\s*/i, "@todo ") + content = content&.gsub(/^\s*NOTE:\s*/i, "@note ") + # Ignore non-documentation comments. - content = content&.sub(/(\A(typed|.*rubocop)|TODO|FIXME):.*/m, "") + content = content&.sub(/\A(typed|.*rubocop):.*/m, "") content = super(content) + source = handler&.statement&.source + + if object&.type == :method && + (match = source&.match(/\so(deprecated|disabled)\s+"((?:\\"|[^"])*)"(?:\s*,\s*"((?:\\"|[^"])*))?"/m)) + type = match[1] + method = match[2] + method = method.sub(/\#{self(\.class)?}/, object.namespace.to_s) + replacement = match[3] + replacement = replacement.sub(/\#{self(\.class)?}/, object.namespace.to_s) + + # Only match `odeprecated`/`odisabled` for this method. + if method.match?(/(.|#|`)#{Regexp.escape(object.name.to_s)}`/) + if (method_name = method[/\A`([^`]*)`\Z/, 1]) && ( + (method_name.count(".") + method_name.count("#")) <= 1 + ) + method_name = method_name.delete_prefix(object.namespace.to_s) + method = (method_name.delete_prefix(".") == object.name(true).to_s) ? nil : "{#{method_name}}" + end + + if replacement && + (replacement_method_name = replacement[/\A`([^`]*)`\Z/, 1]) && ( + (replacement_method_name.count(".") + replacement_method_name.count("#")) <= 1 + ) + replacement_method_name = replacement_method_name.delete_prefix(object.namespace.to_s) + replacement = "{#{replacement_method_name}}" + end + + if method && !method.include?('#{') + description = "Calling #{method} is #{type}" + description += ", use #{replacement} instead" if replacement && !replacement.include?('#{') + description += "." + elsif replacement && !replacement.include?('#{') + description = "Use #{replacement} instead." + else + description = "" + end + + tags << create_tag("deprecated", description) + end + end + + api = tags.find { |tag| tag.tag_name == "api" }&.text + is_private = tags.any? { |tag| tag.tag_name == "private" } + visibility = directives.find { |d| d.tag.tag_name == "visibility" }&.tag&.text + + # Hide `#hash`, `#inspect` and `#to_s`. + if visibility.nil? && OVERRIDABLE_METHODS.include?(object&.name) + create_directive("visibility", "private") + visibility = "private" + end + # Mark everything as `@api private` by default. - visibility_tags = ["visibility", "api", "private"] - tags << create_tag("api", "private") if tags.none? { |tag| visibility_tags.include?(tag.tag_name) } + if api.nil? && !is_private + tags << create_tag("api", "private") + api = "private" + end + + # Warn about undocumented non-private APIs. + if handler && api && api != "private" && visibility != "private" && + content.chomp.empty? && !SELF_EXPLANATORY_METHODS.include?(object&.name) + stmt = handler.statement + log.warn "#{api.capitalize} API should be documented:\n " \ + "in `#{handler.parser.file}`:#{stmt.line}:\n\n#{stmt.show}\n" + end content end