module RubyBreaker::TypeUnparser
This module prints the RubyBreaker
types in a user-friendly way.
Public Class Methods
unparse(t, opts={})
click to toggle source
This method unparses the RubyBreaker
type according to the specified options.
- t
-
RubyBreaker
type - opts
# File lib/rubybreaker/type/type_unparser.rb, line 164 def self.unparse(t, opts={}) str = "" pp = PrettyPrint.new(str) self.unparse_pp(pp, t, opts) pp.flush return str.strip() end
Private Class Methods
peek_and_unparse_pp_inner_type(pp, t, opts={})
click to toggle source
This method is used to determine if the inner type of t
should be wrapped around a parenthesis. This is for optional type and variable length type.
# File lib/rubybreaker/type/type_unparser.rb, line 50 def self.peek_and_unparse_pp_inner_type(pp, t, opts={}) if t.type.kind_of?(OrType) pp.text("(") self.unparse_pp(pp, t.type, opts) pp.text(")") else self.unparse_pp(pp, t.type, opts) end end
resolve_namespace(namespace, mod_name)
click to toggle source
This method resolves the mod_name’s namespace with respect to the namespace. For example, if the current namespace is
A::B
and the given module is A::B::C::D, then we show
C::D
If the current namespace is
A::B::C
and the given module is A::B::D::E, then we show
D::E
# File lib/rubybreaker/type/type_unparser.rb, line 36 def self.resolve_namespace(namespace, mod_name) return mod_name if namespace == nil || namespace.empty? if mod_name.start_with?(namespace) pattern = "^#{namespace}::" return mod_name.sub(/#{pattern}/, "") end tokens = namespace.split("::") return mod_name if tokens.size <= 1 return self.resolve_namespace(tokens[0..-2].join("::"), mod_name) end
unparse_pp(pp, t, opts={})
click to toggle source
This recursive method unparses a RubyBreaker
type using the pretty print method.
# File lib/rubybreaker/type/type_unparser.rb, line 67 def self.unparse_pp(pp, t, opts={}) if t.instance_of?(NominalType) if opts[:namespace] && opts[:namespace].name # resolve the namespace for the module/class given the current # namespace mod_name = self.resolve_namespace(opts[:namespace].name, t.mod.name) else mod_name = t.mod.name end unless opts[:style] == :camelize tname = Util.underscore(mod_name) else tname = mod_name end # tokens = tname.split("/") # tname = tokens.last if tokens.size > 1 pp.text(tname) elsif t.instance_of?(SelfType) pp.text("self") elsif t.instance_of?(DuckType) unparse_pp_object_type(pp,t) elsif t.instance_of?(FusionType) unparse_pp(pp, t.nom_type, opts) unparse_pp_object_type(pp,t) elsif t.instance_of?(MethodType) pp.text("#{t.meth_name}(") t.arg_types.each_with_index do |arg_type,i| unparse_pp(pp, arg_type, opts) if i < t.arg_types.size - 1 pp.text(", ") end end pp.text(")") pp.fill_breakable() if t.blk_type pp.text("{") unparse_pp(pp, t.blk_type, opts) pp.text("}") pp.fill_breakable() end pp.text("-> ") unparse_pp(pp, t.ret_type, opts) elsif t.instance_of?(BlockType) pp.text("|") t.arg_types.each_with_index do |arg_type,i| unparse_pp(pp, arg_type, opts) if i < t.arg_types.size - 1 pp.text(", ") end end pp.text("|") pp.fill_breakable() if t.blk_type pp.text("{") unparse_pp(pp, t.blk_type, opts) pp.text("}") pp.fill_breakable() end pp.text("-> ") unparse_pp(pp, t.ret_type, opts) elsif t.instance_of?(MethodListType) t.types.each_with_index do |typ,i| unparse_pp(pp, typ, opts) if i < t.types.size - 1 pp.fill_breakable() end end elsif t.instance_of?(OrType) t.types.each_with_index do |typ,i| unparse_pp(pp, typ, opts) if i < t.types.size - 1 pp.text(" ||") pp.fill_breakable() end end elsif t.instance_of?(OptionalType) peek_and_unparse_pp_inner_type(pp, t, opts) pp.text("?") elsif t.instance_of?(VarLengthType) peek_and_unparse_pp_inner_type(pp, t, opts) pp.text("*") elsif t.instance_of?(NilType) pp.text("nil") elsif t.instance_of?(AnyType) pp.text("?") else end end
unparse_pp_object_type(pp,t)
click to toggle source
This method unparses an object type (a duck type or fusion type)
# File lib/rubybreaker/type/type_unparser.rb, line 61 def self.unparse_pp_object_type(pp,t) pp.text("[#{t.meth_names.sort.join(", ")}]") end