78 lines
2.8 KiB
Ruby
Raw Normal View History

# typed: strict
# frozen_string_literal: true
require_relative "../../../global"
2024-03-15 15:50:07 -07:00
require "cli/parser"
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
# 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
Homebrew::AbstractCommand.subclasses
2024-03-13 21:55:59 -07:00
end
sig { override.void }
def decorate
cmd = T.cast(constant, T.class_of(Homebrew::AbstractCommand))
# 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
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)
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)
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?("?")
"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
end
end
end