# typed: strict # frozen_string_literal: true require_relative "../../../global" require "sorbet/tapioca/utils" require "debrew" module Tapioca module Compilers class Attrables < Tapioca::Dsl::Compiler ATTRABLE_FILENAME = "attrable.rb" ConstantType = type_member { { fixed: Module } } sig { override.returns(T::Enumerable[Module]) } def self.gather_constants ObjectSpace.each_object(Attrable).map { |obj| obj.name.nil? ? obj.attached_object : obj } end sig { override.void } def decorate root.create_path(constant) do |klass| Homebrew::Tapioca::Utils.methods_from_file(constant, ATTRABLE_FILENAME) .each { |method| compile_attrable_method(klass, method) } Homebrew::Tapioca::Utils.methods_from_file(constant, ATTRABLE_FILENAME, class_methods: true) .each { |method| compile_attrable_method(klass, method, class_method: true) } end end private sig { params(klass: RBI::Scope, method: T.any(Method, UnboundMethod), class_method: T::Boolean).void } def compile_attrable_method(klass, method, class_method: false) case method.arity when -1 # attr_rw klass.create_method( method.name.to_s, parameters: [create_opt_param("arg", type: "T.untyped", default: "nil")], return_type: "T.untyped", class_method:, ) when 0 # attr_predicate klass.create_method( method.name.to_s, return_type: "T::Boolean", class_method:, ) else raise "Unsupported arity for method #{method.name} - did `Attrable` change?" end end end end end