lib/danger/plugin_support/plugin_parser.rb in danger-0.8.5 vs lib/danger/plugin_support/plugin_parser.rb in danger-0.9.0

- old
+ new

@@ -1,10 +1,10 @@ require 'json' -=begin +=begin - So you want to improve this? Great. Hard thing is getting yourself into a position where you + So you want to improve this? Great. Hard thing is getting yourself into a position where you have access to all the tokens, so here's something you should run in `bundle exec pry` to dig in: require 'danger' require 'yard' parser = Danger::PluginParser.new "spec/fixtures/plugins/example_fully_documented.rb" @@ -13,35 +13,33 @@ git = plugins.first klass = git parser.to_dict(plugins) Then some helpers - + attribute_meths = klass.attributes[:instance].values.map(&:values).flatten methods = klass.meths - klass.inherited_meths - attribute_meths usable_methods = methods.select { |m| m.visibility == :public }.reject { |m| m.name == :initialize } - the alternative, is to add require 'pry' binding.pry anywhere inside the source code below. =end - module Danger class PluginParser attr_accessor :registry def initialize(paths) raise "Path cannot be empty" if paths.empty? - if paths.is_a? String + if paths.kind_of? String @paths = [File.expand_path(paths)] else @paths = paths end end @@ -54,11 +52,11 @@ YARD::Tags::Library.define_tag('availablity', :availablity) files = ["lib/danger/plugin_support/plugin.rb"] + @paths # This turns on YARD debugging # $DEBUG = true - + self.registry = YARD::Registry.load(files, true) end def classes_in_file registry.all(:class).select { |klass| @paths.include? klass.file } @@ -71,33 +69,80 @@ def to_json plugins = plugins_from_classes(classes_in_file) to_dict(plugins).to_json end - def to_dict(classes) - d_meth = lambda do |meth| - return nil if meth.nil? - { - name: meth.name, - body_md: meth.docstring, - params: meth.parameters, - tags: meth.tags.map do |t| - { - name: t.tag_name, - types: t.types - } - end - } + # rubocop:disable Metrics/AbcSize + + def method_return_string(meth) + return "" unless meth[:tags] + + return_value = meth[:tags].find { |t| t[:name] == "return" && t[:types] } + return "" if return_value.nil? + return "" if return_value[:types].nil? + return "" unless return_value[:types].kind_of? Array + + unless return_value.empty? + return "" if return_value[:types].first == "void" + return return_value[:types].first end + "" + end - d_attr = lambda do |attribute| - { - read: d_meth.call(attribute[:read]), - write: d_meth.call(attribute[:write]) - } + def method_params(params) + return {} unless params[:params] + + params_names = params[:params].compact.flat_map(&:first) + params_values = params[:tags].find { |t| t[:name] == "param" } + + return {} if params_values.nil? + return {} if params_values[:types].nil? + + return params_names.map.with_index do |name, index| + { name => params_values[:types][index] } end + end + def method_parser(meth) + return nil if meth.nil? + method = { + name: meth.name, + body_md: meth.docstring, + params: meth.parameters, + tags: meth.tags.map { |t| { name: t.tag_name, types: t.types } } + } + + return_v = method_return_string(method) + params_v = method_params(method) + + # Pull out some derived data + method[:param_couplets] = params_v + method[:return] = return_v + + # Create the center params, `thing: OK, other: Thing` + string_params = params_v.map do |param| + name = param.keys.first + param[name].nil? ? name : name + ": " + param[name] + end.join ", " + + # Wrap it in () if there _are_ params + string_params = "(" + string_params + ")" unless string_params.empty? + # Append the return type if we have one + suffix = return_v.empty? ? "" : " -> #{return_v}" + + method[:one_liner] = meth.name.to_s + string_params + suffix + method + end + + def attribute_parser(attribute) + { + read: method_parser(attribute[:read]), + write: method_parser(attribute[:write]) + } + end + + def to_dict(classes) classes.map do |klass| # Adds the class being parsed into the ruby runtime, so that we can access it's instance_name require klass.file real_klass = Danger.const_get klass.name attribute_meths = klass.attributes[:instance].values.map(&:values).flatten @@ -107,18 +152,17 @@ { name: klass.name.to_s, body_md: klass.docstring, instance_name: real_klass.instance_name, - example_code: klass.tags.select { |t| t.tag_name == "example" }.map { |tag| {:title => tag.name, :text => tag.text} }.compact, - attributes: klass.attributes[:instance].map do |pair| - { pair.first => d_attr.call(pair.last) } - end, - methods: usable_methods.map { |m| d_meth.call(m) }, + example_code: klass.tags.select { |t| t.tag_name == "example" }.map { |tag| { title: tag.name, text: tag.text } }.compact, + attributes: klass.attributes[:instance].map { |pair| { pair.first => attribute_parser(pair.last) } }, + methods: usable_methods.map { |m| method_parser(m) }, tags: klass.tags.select { |t| t.tag_name == "tags" }.map(&:text).compact, see: klass.tags.select { |t| t.tag_name == "see" }.map(&:name).map(&:split).flatten.compact, file: klass.file.gsub(File.expand_path("."), "") } end end + # rubocop:enable Metrics/AbcSize end end