summaryrefslogtreecommitdiff
path: root/jni/ruby/lib/rdoc/stats.rb
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/rdoc/stats.rb
Fresh start
Diffstat (limited to 'jni/ruby/lib/rdoc/stats.rb')
-rw-r--r--jni/ruby/lib/rdoc/stats.rb461
1 files changed, 461 insertions, 0 deletions
diff --git a/jni/ruby/lib/rdoc/stats.rb b/jni/ruby/lib/rdoc/stats.rb
new file mode 100644
index 0000000..94fdd27
--- /dev/null
+++ b/jni/ruby/lib/rdoc/stats.rb
@@ -0,0 +1,461 @@
+##
+# RDoc statistics collector which prints a summary and report of a project's
+# documentation totals.
+
+class RDoc::Stats
+
+ include RDoc::Text
+
+ ##
+ # Output level for the coverage report
+
+ attr_reader :coverage_level
+
+ ##
+ # Count of files parsed during parsing
+
+ attr_reader :files_so_far
+
+ ##
+ # Total number of files found
+
+ attr_reader :num_files
+
+ ##
+ # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1
+ # which will create an RDoc::Stats::Normal outputter.
+
+ def initialize store, num_files, verbosity = 1
+ @num_files = num_files
+ @store = store
+
+ @coverage_level = 0
+ @doc_items = nil
+ @files_so_far = 0
+ @fully_documented = false
+ @num_params = 0
+ @percent_doc = nil
+ @start = Time.now
+ @undoc_params = 0
+
+ @display = case verbosity
+ when 0 then Quiet.new num_files
+ when 1 then Normal.new num_files
+ else Verbose.new num_files
+ end
+ end
+
+ ##
+ # Records the parsing of an alias +as+.
+
+ def add_alias as
+ @display.print_alias as
+ end
+
+ ##
+ # Records the parsing of an attribute +attribute+
+
+ def add_attribute attribute
+ @display.print_attribute attribute
+ end
+
+ ##
+ # Records the parsing of a class +klass+
+
+ def add_class klass
+ @display.print_class klass
+ end
+
+ ##
+ # Records the parsing of +constant+
+
+ def add_constant constant
+ @display.print_constant constant
+ end
+
+ ##
+ # Records the parsing of +file+
+
+ def add_file(file)
+ @files_so_far += 1
+ @display.print_file @files_so_far, file
+ end
+
+ ##
+ # Records the parsing of +method+
+
+ def add_method(method)
+ @display.print_method method
+ end
+
+ ##
+ # Records the parsing of a module +mod+
+
+ def add_module(mod)
+ @display.print_module mod
+ end
+
+ ##
+ # Call this to mark the beginning of parsing for display purposes
+
+ def begin_adding
+ @display.begin_adding
+ end
+
+ ##
+ # Calculates documentation totals and percentages for classes, modules,
+ # constants, attributes and methods.
+
+ def calculate
+ return if @doc_items
+
+ ucm = @store.unique_classes_and_modules
+
+ classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' }
+
+ constants = []
+ ucm.each { |cm| constants.concat cm.constants }
+
+ methods = []
+ ucm.each { |cm| methods.concat cm.method_list }
+
+ attributes = []
+ ucm.each { |cm| attributes.concat cm.attributes }
+
+ @num_attributes, @undoc_attributes = doc_stats attributes
+ @num_classes, @undoc_classes = doc_stats classes
+ @num_constants, @undoc_constants = doc_stats constants
+ @num_methods, @undoc_methods = doc_stats methods
+ @num_modules, @undoc_modules = doc_stats @store.unique_modules
+
+ @num_items =
+ @num_attributes +
+ @num_classes +
+ @num_constants +
+ @num_methods +
+ @num_modules +
+ @num_params
+
+ @undoc_items =
+ @undoc_attributes +
+ @undoc_classes +
+ @undoc_constants +
+ @undoc_methods +
+ @undoc_modules +
+ @undoc_params
+
+ @doc_items = @num_items - @undoc_items
+ end
+
+ ##
+ # Sets coverage report level. Accepted values are:
+ #
+ # false or nil:: No report
+ # 0:: Classes, modules, constants, attributes, methods
+ # 1:: Level 0 + method parameters
+
+ def coverage_level= level
+ level = -1 unless level
+
+ @coverage_level = level
+ end
+
+ ##
+ # Returns the length and number of undocumented items in +collection+.
+
+ def doc_stats collection
+ visible = collection.select { |item| item.display? }
+ [visible.length, visible.count { |item| not item.documented? }]
+ end
+
+ ##
+ # Call this to mark the end of parsing for display purposes
+
+ def done_adding
+ @display.done_adding
+ end
+
+ ##
+ # The documentation status of this project. +true+ when 100%, +false+ when
+ # less than 100% and +nil+ when unknown.
+ #
+ # Set by calling #calculate
+
+ def fully_documented?
+ @fully_documented
+ end
+
+ ##
+ # A report that says you did a great job!
+
+ def great_job
+ report = RDoc::Markup::Document.new
+
+ report << RDoc::Markup::Paragraph.new('100% documentation!')
+ report << RDoc::Markup::Paragraph.new('Great Job!')
+
+ report
+ end
+
+ ##
+ # Calculates the percentage of items documented.
+
+ def percent_doc
+ return @percent_doc if @percent_doc
+
+ @fully_documented = (@num_items - @doc_items) == 0
+
+ @percent_doc = @doc_items.to_f / @num_items * 100 if @num_items.nonzero?
+ @percent_doc ||= 0
+
+ @percent_doc
+ end
+
+ ##
+ # Returns a report on which items are not documented
+
+ def report
+ if @coverage_level > 0 then
+ extend RDoc::Text
+ end
+
+ if @coverage_level.zero? then
+ calculate
+
+ return great_job if @num_items == @doc_items
+ end
+
+ ucm = @store.unique_classes_and_modules
+
+ report = RDoc::Markup::Document.new
+ report << RDoc::Markup::Paragraph.new('The following items are not documented:')
+ report << RDoc::Markup::BlankLine.new
+
+ ucm.sort.each do |cm|
+ body = report_class_module(cm) {
+ [
+ report_constants(cm),
+ report_attributes(cm),
+ report_methods(cm),
+ ].compact
+ }
+
+ report << body if body
+ end
+
+ if @coverage_level > 0 then
+ calculate
+
+ return great_job if @num_items == @doc_items
+ end
+
+ report
+ end
+
+ ##
+ # Returns a report on undocumented attributes in ClassModule +cm+
+
+ def report_attributes cm
+ return if cm.attributes.empty?
+
+ report = []
+
+ cm.each_attribute do |attr|
+ next if attr.documented?
+ line = attr.line ? ":#{attr.line}" : nil
+ report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}\n"
+ report << "\n"
+ end
+
+ report
+ end
+
+ ##
+ # Returns a report on undocumented items in ClassModule +cm+
+
+ def report_class_module cm
+ return if cm.fully_documented? and @coverage_level.zero?
+ return unless cm.display?
+
+ report = RDoc::Markup::Document.new
+
+ if cm.in_files.empty? then
+ report << RDoc::Markup::Paragraph.new("#{cm.definition} is referenced but empty.")
+ report << RDoc::Markup::Paragraph.new("It probably came from another project. I'm sorry I'm holding it against you.")
+
+ return report
+ elsif cm.documented? then
+ documented = true
+ klass = RDoc::Markup::Verbatim.new("#{cm.definition} # is documented\n")
+ else
+ report << RDoc::Markup::Paragraph.new('In files:')
+
+ list = RDoc::Markup::List.new :BULLET
+
+ cm.in_files.each do |file|
+ para = RDoc::Markup::Paragraph.new file.full_name
+ list << RDoc::Markup::ListItem.new(nil, para)
+ end
+
+ report << list
+ report << RDoc::Markup::BlankLine.new
+
+ klass = RDoc::Markup::Verbatim.new("#{cm.definition}\n")
+ end
+
+ klass << "\n"
+
+ body = yield.flatten # HACK remove #flatten
+
+ if body.empty? then
+ return if documented
+
+ klass.parts.pop
+ else
+ klass.parts.concat body
+ end
+
+ klass << "end\n"
+
+ report << klass
+
+ report
+ end
+
+ ##
+ # Returns a report on undocumented constants in ClassModule +cm+
+
+ def report_constants cm
+ return if cm.constants.empty?
+
+ report = []
+
+ cm.each_constant do |constant|
+ # TODO constant aliases are listed in the summary but not reported
+ # figure out what to do here
+ next if constant.documented? || constant.is_alias_for
+
+ line = constant.line ? ":#{constant.line}" : line
+ report << " # in file #{constant.file.full_name}#{line}\n"
+ report << " #{constant.name} = nil\n"
+ report << "\n"
+ end
+
+ report
+ end
+
+ ##
+ # Returns a report on undocumented methods in ClassModule +cm+
+
+ def report_methods cm
+ return if cm.method_list.empty?
+
+ report = []
+
+ cm.each_method do |method|
+ next if method.documented? and @coverage_level.zero?
+
+ if @coverage_level > 0 then
+ params, undoc = undoc_params method
+
+ @num_params += params
+
+ unless undoc.empty? then
+ @undoc_params += undoc.length
+
+ undoc = undoc.map do |param| "+#{param}+" end
+ param_report = " # #{undoc.join ', '} is not documented\n"
+ end
+ end
+
+ next if method.documented? and not param_report
+
+ line = method.line ? ":#{method.line}" : nil
+ scope = method.singleton ? 'self.' : nil
+
+ report << " # in file #{method.file.full_name}#{line}\n"
+ report << param_report if param_report
+ report << " def #{scope}#{method.name}#{method.params}; end\n"
+ report << "\n"
+ end
+
+ report
+ end
+
+ ##
+ # Returns a summary of the collected statistics.
+
+ def summary
+ calculate
+
+ num_width = [@num_files, @num_items].max.to_s.length
+ undoc_width = [
+ @undoc_attributes,
+ @undoc_classes,
+ @undoc_constants,
+ @undoc_items,
+ @undoc_methods,
+ @undoc_modules,
+ @undoc_params,
+ ].max.to_s.length
+
+ report = RDoc::Markup::Verbatim.new
+
+ report << "Files: %*d\n" % [num_width, @num_files]
+
+ report << "\n"
+
+ report << "Classes: %*d (%*d undocumented)\n" % [
+ num_width, @num_classes, undoc_width, @undoc_classes]
+ report << "Modules: %*d (%*d undocumented)\n" % [
+ num_width, @num_modules, undoc_width, @undoc_modules]
+ report << "Constants: %*d (%*d undocumented)\n" % [
+ num_width, @num_constants, undoc_width, @undoc_constants]
+ report << "Attributes: %*d (%*d undocumented)\n" % [
+ num_width, @num_attributes, undoc_width, @undoc_attributes]
+ report << "Methods: %*d (%*d undocumented)\n" % [
+ num_width, @num_methods, undoc_width, @undoc_methods]
+ report << "Parameters: %*d (%*d undocumented)\n" % [
+ num_width, @num_params, undoc_width, @undoc_params] if
+ @coverage_level > 0
+
+ report << "\n"
+
+ report << "Total: %*d (%*d undocumented)\n" % [
+ num_width, @num_items, undoc_width, @undoc_items]
+
+ report << "%6.2f%% documented\n" % percent_doc
+ report << "\n"
+ report << "Elapsed: %0.1fs\n" % (Time.now - @start)
+
+ RDoc::Markup::Document.new report
+ end
+
+ ##
+ # Determines which parameters in +method+ were not documented. Returns a
+ # total parameter count and an Array of undocumented methods.
+
+ def undoc_params method
+ @formatter ||= RDoc::Markup::ToTtOnly.new
+
+ params = method.param_list
+
+ params = params.map { |param| param.gsub(/^\*\*?/, '') }
+
+ return 0, [] if params.empty?
+
+ document = parse method.comment
+
+ tts = document.accept @formatter
+
+ undoc = params - tts
+
+ [params.length, undoc]
+ end
+
+ autoload :Quiet, 'rdoc/stats/quiet'
+ autoload :Normal, 'rdoc/stats/normal'
+ autoload :Verbose, 'rdoc/stats/verbose'
+
+end
+