class Solargraph::LiveParser
def self.parse n
def self.parse n LiveParser.new.parse(n) end
def build_args method
def build_args method args = "" if (method.arity == -1) args = "(*args)" else arr = [] num = 0 method.parameters.each { |p| n = p[1] if n.to_s == "" n = "arg#{num}" end if p[0] == :req arr.push "#{n}" elsif p[0] == :opt arr.push "#{n} = nil" elsif p[0] == :rest arr.push "*#{n}" elsif p[0] == :block arr.push "&#{n}" end num += 1 } args = "(" + arr.join(", ") + ")" end args end
def can_ignore?(obj, sym)
def can_ignore?(obj, sym) #return false basics = [Kernel, Module, Object, BasicObject] return false if basics.include?(obj) result = false basics.each { |b| if b.respond_to?(sym) result = true break end } return result end
def get_yard_return(path)
def get_yard_return(path) objects = [] yardocs = ['yard/2.2.0/.yardoc', 'ruby/yard/2.2.0/.yardoc-stdlib'] yardocs.each { |y| YARD::Registry.load!(y) o = YARD::Registry.at(path) if !o.nil? objects.push o end } result = nil objects.each { |x| meth = x if !meth.tag(:return) and meth.tag(:overload) and meth.tag(:overload).tag(:return) meth = meth.tag(:overload) end meth.tags(:return).each { |r| result = "#{r.types[0]}" break } break if !result.nil? } result end
def initialize
def initialize end
def parse namespace = nil
def parse namespace = nil #puts "Namespace: #{namespace}" @parsed = [] code = "" fqns = namespace if fqns.nil? #code += parse("BasicObject") #code += parse("Object") #code += parse("Kernel") code += parse("Module") return code end mod = eval("#{fqns}") if !mod.nil? if mod.instance_of?(Class) #puts "Parsing class #{mod} to #{fqns}" code += parse_class mod, fqns elsif mod.instance_of?(Module) #puts "Parsing module #{mod} to #{fqns}" code += parse_module mod, fqns else #raise "I don't know what a #{fqns} is." code += "#{fqns} = nil\n" end else #puts "NIL!" end code end
def parse_class cls, rel_name
def parse_class cls, rel_name return "" if @parsed.include?(cls) @parsed.push cls code = "" #code += "class #{rel_name}" code += "class #{cls}" if !cls.superclass.nil? && cls.superclass != cls code += " < #{cls.superclass}" end code += "\n" code += parse_class_internals(cls) code += "end\n" cls.constants().each { |c| #obj = cls.class_eval(c.to_s) begin obj = cls.const_get(c) if obj.kind_of?(Class) code += parse_class(obj, c) elsif obj.kind_of?(Module) code += parse_module(obj, c) else #code += subparse(obj) end #rescue NameError => e # #puts "NOPE! NOT #{c}" #end rescue Exception => e # TODO: Ignoring all exceptions for now end } code end
def parse_class_internals obj
def parse_class_internals obj code = "" obj.included_modules.each { |inc| #if (inc.to_s != "Kernel") code += "include #{inc}\n" #end } obj.public_methods(false).each { |m| if !can_ignore?(obj, m) args = build_args obj.method(m) #ret = get_yard_return "#{obj}::#{m}" #if !ret.nil? # code += "# @return [#{ret}]\n" #end code += "def self.#{m}#{args};end\n" end } alloc = obj obj.singleton_methods(false).each { |m| if !can_ignore?(obj, m) args = build_args obj.method(m) #ret = get_yard_return "#{obj}::#{m}" #if !ret.nil? # code += "# @return [#{ret}]\n" #end code += "def self.#{m}#{args};end\n" end } obj.public_instance_methods(false).each { |m| if !can_ignore?(obj, m) begin args = build_args obj.public_instance_method(m) rescue TypeError => e args = "" end #ret = get_yard_return "#{obj}##{m}" #if !ret.nil? # code += "# @return [#{ret}]\n" #end code += "def #{m}#{args};end\n" end } code end
def parse_module mod, rel_name
def parse_module mod, rel_name return "" if @parsed.include?(mod) or mod == Solargraph @parsed.push mod code = "" #if (mod.to_s != "Kernel") code = "module #{mod}\n" #end code += parse_module_internals(mod) #if (mod.to_s != "Kernel") code += "end\n" #end mod.constants().each { |c| #obj = mod.class_eval(c.to_s) begin obj = mod.const_get(c) rescue LoadError => e code += "# @todo Failed to load #{c} from #{mod}\n" end if obj.kind_of?(Class) code += parse_class(obj, c) elsif obj.kind_of?(Module) code += parse_module(obj, c) else #code += subparse(obj) end } code end
def parse_module_internals obj
def parse_module_internals obj code = "" obj.included_modules.each { |inc| #if (inc.to_s != "Kernel") code += "include #{inc}\n" #end } obj.public_methods(false).each { |m| if obj == Kernel #and obj.singleton_methods.include?(m) next end if !can_ignore?(obj, m) args = build_args obj.method(m) #ret = get_yard_return "#{obj}##{m}" #if !ret.nil? # code += "# @return [#{ret}]\n" #end code += "def #{m}#{args};end\n" end } obj.singleton_methods(false).each { |m| if !can_ignore?(obj, m) args = build_args obj.method(m) #ret = get_yard_return "#{obj}::#{m}" #if !ret.nil? # code += "# @return [#{ret}]\n" #end code += "def self.#{m}#{args};end\n" end } #obj.public_instance_methods(false).each { |m| obj.public_instance_methods(false).each { |m| #if !can_ignore?(obj, m) args = build_args obj.public_instance_method(m) #ret = get_yard_return "#{obj}##{m}" #if !ret.nil? # code += "# @return [#{ret}]\n" #end code += "def #{m}#{args};end\n" #end } code end