# frozen_string_literal: true module Anyway module RBSGenerator TYPE_TO_CLASS = { string: "String", integer: "Integer", float: "Float", date: "Date", datetime: "DateTime", uri: "URI", boolean: "bool" }.freeze # Generate RBS signature from a config class def to_rbs *namespace, class_name = name.split("::") buf = [] indent = 0 interface_name = "_Config" if namespace.empty? interface_name = "_#{class_name}" else buf << "module #{namespace.join("::")}" indent += 1 end # Using interface emulates a module we include to provide getters and setters # (thus making `super` possible) buf << "#{" " * indent}interface #{interface_name}" indent += 1 # Generating setters and getters for config attributes config_attributes.each do |param| type = coercion_mapping[param] || defaults[param.to_s] type = case type in NilClass "untyped" in Symbol TYPE_TO_CLASS.fetch(type) { defaults[param] ? "Symbol" : "untyped" } in Array "Array[untyped]" in array: _, type:, **nil "Array[#{TYPE_TO_CLASS.fetch(type, "untyped")}]" in Hash "Hash[string,untyped]" in TrueClass | FalseClass "bool" else type.class.to_s end getter_type = type getter_type = "#{type}?" unless required_attributes.include?(param) buf << "#{" " * indent}def #{param}: () -> #{getter_type}" buf << "#{" " * indent}def #{param}=: (#{type}) -> void" if type == "bool" || type == "bool?" buf << "#{" " * indent}def #{param}?: () -> #{getter_type}" end end indent -= 1 buf << "#{" " * indent}end" buf << "" buf << "#{" " * indent}class #{class_name} < #{superclass.name}" indent += 1 buf << "#{" " * indent}include #{interface_name}" indent -= 1 buf << "#{" " * indent}end" unless namespace.empty? buf << "end" end buf << "" buf.join("\n") end end Config.extend RBSGenerator end