Class: Argtrace::OutputModule
- Inherits:
-
Object
- Object
- Argtrace::OutputModule
- Defined in:
- lib/argtrace/typelib.rb
Overview
helper to convert TypeLib into RBS. OutputMoudle acts like Module tree node.
Instance Attribute Summary collapse
-
#actual_module ⇒ Object
Returns the value of attribute actual_module.
-
#children ⇒ Object
Returns the value of attribute children.
-
#name ⇒ Object
Returns the value of attribute name.
-
#signatures ⇒ Object
Returns the value of attribute signatures.
Instance Method Summary collapse
- #add_signature(signature) ⇒ Object
- #add_signature_inner(name_consts, signature) ⇒ Object
- #blocktype_to_rbs(blockparam) ⇒ Object
-
#class_const_name(klass) ⇒ Object
split class name into consts (e.g. Argtrace::TypeLib to [“Argtrace”, “TypeLib”]).
-
#initialize ⇒ OutputModule
constructor
A new instance of OutputModule.
- #param_to_rbs(param) ⇒ Object
- #sig_to_rbs(indent_level, signature) ⇒ Object
- #to_rbs ⇒ Object
- #to_rbs_inner(indent_level) ⇒ Object
- #type_to_rbs(type) ⇒ Object
- #type_union_to_rbs(typeunion) ⇒ Object
Constructor Details
#initialize ⇒ OutputModule
Returns a new instance of OutputModule.
66 67 68 69 |
# File 'lib/argtrace/typelib.rb', line 66 def initialize @children = {} @signatures = [] end |
Instance Attribute Details
#actual_module ⇒ Object
Returns the value of attribute actual_module.
64 65 66 |
# File 'lib/argtrace/typelib.rb', line 64 def actual_module @actual_module end |
#children ⇒ Object
Returns the value of attribute children.
64 65 66 |
# File 'lib/argtrace/typelib.rb', line 64 def children @children end |
#name ⇒ Object
Returns the value of attribute name.
64 65 66 |
# File 'lib/argtrace/typelib.rb', line 64 def name @name end |
#signatures ⇒ Object
Returns the value of attribute signatures.
64 65 66 |
# File 'lib/argtrace/typelib.rb', line 64 def signatures @signatures end |
Instance Method Details
#add_signature(signature) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/argtrace/typelib.rb', line 71 def add_signature(signature) # this is root node, so use Kernel as const resolve source. @actual_module = Kernel constname = class_const_name(signature.defined_class) unless constname # cannot handle this return end add_signature_inner(constname, signature) end |
#add_signature_inner(name_consts, signature) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/argtrace/typelib.rb', line 105 def add_signature_inner(name_consts, signature) if name_consts.empty? @signatures << signature else unless @children.key?(name_consts.first) mod = OutputModule.new mod.name = name_consts.first mod.actual_module = @actual_module.const_get(name_consts.first) @children[name_consts.first] = mod end current_resolving_name = name_consts.shift @children[current_resolving_name].add_signature_inner(name_consts, signature) end end |
#blocktype_to_rbs(blockparam) ⇒ Object
160 161 162 163 164 165 166 167 168 |
# File 'lib/argtrace/typelib.rb', line 160 def blocktype_to_rbs(blockparam) unless blockparam return "" end params = blockparam.type.params .map{|p| type_union_to_rbs(p.type)} .join(", ") return " { (#{params}) -> untyped }" end |
#class_const_name(klass) ⇒ Object
split class name into consts (e.g. Argtrace::TypeLib to [“Argtrace”, “TypeLib”])
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/argtrace/typelib.rb', line 85 def class_const_name(klass) if /^[A-Za-z0-9_:]+$/ =~ klass.to_s # this should be normal name consts = klass.to_s.split("::") # assertion resolved_class = consts.inject(Kernel){|mod, const| mod.const_get(const)} if klass != resolved_class $stderr.puts "----- argtrace bug -----" $stderr.puts "#{klass} => #{consts} => #{resolved_class}" $stderr.puts "------------------------" raise "Failed to resolve class by constant" end return consts else return nil end end |
#param_to_rbs(param) ⇒ Object
170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/argtrace/typelib.rb', line 170 def param_to_rbs(param) case param.mode when :req return "#{type_union_to_rbs(param.type)} #{param.name}" when :opt return "?#{type_union_to_rbs(param.type)} #{param.name}" when :keyreq return "#{param.name}: #{type_union_to_rbs(param.type)}" when :key return "?#{param.name}: #{type_union_to_rbs(param.type)}" when :block return nil end end |
#sig_to_rbs(indent_level, signature) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/argtrace/typelib.rb', line 147 def sig_to_rbs(indent_level, signature) indent = " " * indent_level sig_name = signature.is_singleton_method ? "self.#{signature.method_id}" : signature.method_id params = signature.params .filter{|p| p.mode != :block} .map{|p| param_to_rbs(p)} .compact .join(", ") rettype = type_union_to_rbs(signature.return_type) blocktype = blocktype_to_rbs(signature.params.find{|p| p.mode == :block}) return "#{indent}def #{sig_name} : (#{params})#{blocktype} -> #{rettype}" end |
#to_rbs ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/argtrace/typelib.rb', line 120 def to_rbs # this is root node lines = [] @children.keys.sort.each do |child_name| lines << @children[child_name].to_rbs_inner(0) lines << "" end return lines.join("\n") end |
#to_rbs_inner(indent_level) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/argtrace/typelib.rb', line 130 def to_rbs_inner(indent_level) indent = " " * indent_level classmod_def = @actual_module.class == Class ? "class" : "module" lines = [] lines << "#{indent}#{classmod_def} #{name}" @children.keys.sort.each do |child_name| lines << @children[child_name].to_rbs_inner(indent_level + 1) lines << "" end @signatures.each do |sig| lines << sig_to_rbs(indent_level + 1, sig) end lines << "#{indent}end" return lines.join("\n") end |
#type_to_rbs(type) ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/argtrace/typelib.rb', line 204 def type_to_rbs(type) if type.data.is_a?(Symbol) return type.data.inspect elsif true == type.data || false == type.data || BooleanClass == type.data return "bool" elsif nil == type.data || NilClass == type.data return "nil" elsif Array == type.data if type.subdata case type.subdata when true, false, BooleanClass elementtype = "bool" else elementtype = type.subdata.to_s end return "Array[#{elementtype}]" else return "Array" end else return type.data.to_s end end |
#type_union_to_rbs(typeunion) ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/argtrace/typelib.rb', line 185 def type_union_to_rbs(typeunion) if typeunion.union.size == 0 return "untyped" end # TODO: ugly if typeunion.union.size == 1 and NilClass == typeunion.union.first.data # TODO: I can't distinguish nil and untyped. return "untyped" end if typeunion.union.size == 2 and typeunion.union.any?{|x| NilClass == x.data} # type is nil and sometype, so represent it as "sometype?" sometype = typeunion.union.find{|x| NilClass != x.data} return "#{type_to_rbs(sometype)}?" end ret = typeunion.union.map{|type| type_to_rbs(type)}.join("|") return ret end |