2024-03-11 23:00:15 -07:00
|
|
|
# typed: strict
|
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require_relative "../../../global"
|
2024-03-15 15:50:07 -07:00
|
|
|
require "cli/parser"
|
2024-03-11 23:00:15 -07:00
|
|
|
|
|
|
|
module Tapioca
|
|
|
|
module Compilers
|
|
|
|
class Args < Tapioca::Dsl::Compiler
|
2024-03-15 15:50:07 -07:00
|
|
|
GLOBAL_OPTIONS = T.let(
|
2024-03-17 09:29:40 -07:00
|
|
|
Homebrew::CLI::Parser.global_options.map do |short_option, long_option, _|
|
|
|
|
[short_option, long_option].map { "#{Homebrew::CLI::Parser.option_to_name(_1)}?" }
|
|
|
|
end.flatten.freeze, T::Array[String]
|
2024-03-15 15:50:07 -07:00
|
|
|
)
|
|
|
|
|
2024-03-15 14:24:26 -07:00
|
|
|
Parsable = T.type_alias { T.any(T.class_of(Homebrew::CLI::Args), T.class_of(Homebrew::AbstractCommand)) }
|
2024-03-15 15:50:07 -07:00
|
|
|
ConstantType = type_member { { fixed: Parsable } }
|
2024-03-15 14:24:26 -07:00
|
|
|
sig { override.returns(T::Enumerable[Parsable]) }
|
2024-03-13 21:55:59 -07:00
|
|
|
def self.gather_constants
|
2024-07-31 17:30:31 +01:00
|
|
|
# require all the commands to ensure the command subclasses are defined
|
2024-03-13 21:55:59 -07:00
|
|
|
["cmd", "dev-cmd"].each do |dir|
|
|
|
|
Dir[File.join(__dir__, "../../../#{dir}", "*.rb")].each { require(_1) }
|
|
|
|
end
|
2024-07-31 17:30:31 +01:00
|
|
|
Homebrew::AbstractCommand.subclasses
|
2024-03-13 21:55:59 -07:00
|
|
|
end
|
2024-03-11 23:00:15 -07:00
|
|
|
|
|
|
|
sig { override.void }
|
|
|
|
def decorate
|
2024-07-31 17:30:31 +01:00
|
|
|
cmd = T.cast(constant, T.class_of(Homebrew::AbstractCommand))
|
2024-08-15 07:59:49 -07:00
|
|
|
# This is a dummy class to make the `brew` command parsable
|
2024-08-15 08:18:31 -07:00
|
|
|
return if cmd == Homebrew::Cmd::Brew
|
2024-08-15 07:59:49 -07:00
|
|
|
|
2024-07-31 17:30:31 +01:00
|
|
|
args_class_name = T.must(T.must(cmd.args_class).name)
|
|
|
|
root.create_class(args_class_name, superclass_name: "Homebrew::CLI::Args") do |klass|
|
|
|
|
create_args_methods(klass, cmd.parser)
|
|
|
|
end
|
|
|
|
root.create_path(constant) do |klass|
|
|
|
|
klass.create_method("args", return_type: args_class_name)
|
2024-03-11 23:00:15 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-11-30 13:52:46 -08:00
|
|
|
sig { params(parser: Homebrew::CLI::Parser).returns(T::Array[Symbol]) }
|
|
|
|
def args_table(parser) = parser.args.methods(false)
|
2024-03-13 21:55:59 -07:00
|
|
|
|
|
|
|
sig { params(parser: Homebrew::CLI::Parser).returns(T::Array[Symbol]) }
|
|
|
|
def comma_arrays(parser)
|
|
|
|
parser.instance_variable_get(:@non_global_processed_options)
|
|
|
|
.filter_map { |k, v| parser.option_to_name(k).to_sym if v == :comma_array }
|
|
|
|
end
|
|
|
|
|
2024-11-30 13:52:46 -08:00
|
|
|
sig { params(method_name: Symbol, comma_array_methods: T::Array[Symbol]).returns(String) }
|
|
|
|
def get_return_type(method_name, comma_array_methods)
|
2024-03-11 23:00:15 -07:00
|
|
|
if comma_array_methods.include?(method_name)
|
|
|
|
"T.nilable(T::Array[String])"
|
2024-11-30 13:52:46 -08:00
|
|
|
elsif method_name.end_with?("?")
|
2024-03-11 23:00:15 -07:00
|
|
|
"T::Boolean"
|
|
|
|
else
|
|
|
|
"T.nilable(String)"
|
|
|
|
end
|
|
|
|
end
|
2024-03-15 14:24:26 -07:00
|
|
|
|
|
|
|
private
|
|
|
|
|
2024-03-16 08:35:02 -07:00
|
|
|
sig { params(klass: RBI::Scope, parser: Homebrew::CLI::Parser).void }
|
|
|
|
def create_args_methods(klass, parser)
|
2024-03-15 14:24:26 -07:00
|
|
|
comma_array_methods = comma_arrays(parser)
|
2024-11-30 13:52:46 -08:00
|
|
|
args_table(parser).each do |method_name|
|
2024-03-15 15:50:07 -07:00
|
|
|
method_name_str = method_name.to_s
|
2024-03-16 08:35:02 -07:00
|
|
|
next if GLOBAL_OPTIONS.include?(method_name_str)
|
2024-03-15 14:24:26 -07:00
|
|
|
|
2024-11-30 13:52:46 -08:00
|
|
|
return_type = get_return_type(method_name, comma_array_methods)
|
2024-03-15 15:50:07 -07:00
|
|
|
klass.create_method(method_name_str, return_type:)
|
2024-03-15 14:24:26 -07:00
|
|
|
end
|
|
|
|
end
|
2024-03-11 23:00:15 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|