├── Rakefile ├── lib ├── documetrix │ ├── version.rb │ ├── documetrix.rb │ └── store.rb ├── documetrix.rb └── rdoc │ └── discover.rb ├── .gitignore ├── Gemfile ├── README.md └── documetrix.gemspec /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /lib/documetrix/version.rb: -------------------------------------------------------------------------------- 1 | module Documetrix 2 | VERSION = "0.0.1" 3 | end 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | pkg/* 5 | lib/.DS_Store 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in documetrix.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/documetrix.rb: -------------------------------------------------------------------------------- 1 | require "rdoc/rdoc" 2 | require_relative "documetrix/documetrix" 3 | 4 | module Documetrix 5 | 6 | end -------------------------------------------------------------------------------- /lib/rdoc/discover.rb: -------------------------------------------------------------------------------- 1 | begin 2 | gem 'rdoc', '~> 3' 3 | require_relative '../documetrix/documetrix' 4 | rescue Gem::LoadError 5 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Custom RDoc generator to quantify documentation coverage. 2 | 3 | It will count the number of documentation words in classes, modules and methods and compare them to the standards set by other Ruby libraries. 4 | -------------------------------------------------------------------------------- /documetrix.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "documetrix/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "documetrix" 7 | s.version = Documetrix::VERSION 8 | s.authors = ["madebydna"] 9 | s.email = ["info@madebydna.com"] 10 | s.homepage = "" 11 | s.summary = %q{Generates reports to quantify documentation coverage} 12 | s.description = %q{Generates reports to quantify documentation coverage, also in comparision with documentation standards set by other ruby gems} 13 | 14 | s.rubyforge_project = "documetrix" 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 18 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 19 | s.require_paths = ["lib"] 20 | 21 | # specify any dependencies here; for example: 22 | # s.add_development_dependency "rspec" 23 | s.add_runtime_dependency "rdoc" 24 | end 25 | -------------------------------------------------------------------------------- /lib/documetrix/documetrix.rb: -------------------------------------------------------------------------------- 1 | require_relative "store" 2 | 3 | module Documetrix 4 | class Documetrix 5 | RDoc::RDoc.add_generator self 6 | 7 | ## 8 | # Description of this generator 9 | 10 | DESCRIPTION = 'creates report on documentation coverage' 11 | 12 | def initialize options 13 | @options = options 14 | @old_siginfo = nil 15 | @current = nil 16 | 17 | @store = Store.new 18 | @store.dry_run = @options.dry_run 19 | @store.encoding = @options.encoding if @options.respond_to? :encoding 20 | end 21 | 22 | def generate top_levels 23 | install_siginfo_handler 24 | 25 | RDoc::TopLevel.all_classes_and_modules.each do |klass| 26 | @current = "#{klass.class}: #{klass.full_name}" 27 | 28 | @store.save_class klass 29 | end 30 | 31 | @current = 'saving cache' 32 | 33 | @store.save_cache 34 | 35 | ensure 36 | @current = nil 37 | 38 | remove_siginfo_handler 39 | end 40 | 41 | ## 42 | # Installs a siginfo handler that prints the current filename. 43 | 44 | def install_siginfo_handler 45 | return unless Signal.list.key? 'INFO' 46 | 47 | @old_siginfo = trap 'INFO' do 48 | puts @current if @current 49 | end 50 | end 51 | 52 | ## 53 | # Removes a siginfo handler and replaces the previous 54 | 55 | def remove_siginfo_handler 56 | return unless Signal.list.key? 'INFO' 57 | 58 | handler = @old_siginfo || 'DEFAULT' 59 | 60 | trap 'INFO', handler 61 | end 62 | 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/documetrix/store.rb: -------------------------------------------------------------------------------- 1 | module Documetrix 2 | class Store 3 | 4 | ## 5 | # If true this Store will not do anything 6 | 7 | attr_accessor :dry_run 8 | 9 | ## 10 | # The encoding of the contents in the Store 11 | 12 | attr_accessor :encoding 13 | 14 | ## 15 | # The contents of the Store 16 | 17 | attr_reader :cache 18 | 19 | def initialize 20 | @dry_run = false 21 | @encoding = nil 22 | 23 | @cache = { 24 | :attributes => {}, 25 | :class_methods => {}, 26 | :instance_methods => {}, 27 | :modules => {}, 28 | } 29 | end 30 | 31 | 32 | def save_class klass 33 | full_name = klass.full_name 34 | 35 | @cache[:modules][full_name] ||= 0 36 | @cache[:modules][full_name] += comment_word_count(klass.comment) 37 | 38 | @cache[:attributes][full_name] ||= {} 39 | 40 | klass.attributes.each do |attribute| 41 | @cache[:attributes][full_name][attribute.name] ||= 0 42 | @cache[:attributes][full_name][attribute.name] += comment_word_count(attribute.comment) 43 | end 44 | 45 | unless klass.method_list.empty? 46 | @cache[:class_methods][full_name] ||= {} 47 | @cache[:instance_methods][full_name] ||= {} 48 | 49 | class_methods, instance_methods = 50 | klass.method_list.partition { |meth| meth.singleton } 51 | 52 | class_methods.each do |class_method| 53 | @cache[:class_methods][full_name][class_method.name] ||= 0 54 | @cache[:class_methods][full_name][class_method.name] += comment_word_count(class_method.comment) 55 | end 56 | 57 | instance_methods.each do |instance_method| 58 | @cache[:instance_methods][full_name][instance_method.name] ||= 0 59 | @cache[:instance_methods][full_name][instance_method.name] += comment_word_count(instance_method.comment) 60 | end 61 | end 62 | end 63 | 64 | ## 65 | # Gets naive comment word count 66 | 67 | def comment_word_count comment 68 | comment = comment.text unless comment.is_a?(String) 69 | comment.split(/\s+/).length 70 | end 71 | 72 | ## 73 | # Writes the cache file for this store 74 | 75 | def save_cache 76 | return if @dry_run 77 | 78 | print_cache 79 | end 80 | 81 | def print_cache 82 | File.open "./coverage_report.txt", 'wb' do |file| 83 | @cache[:modules].each do |klass, wcount| 84 | file.write "#{klass}: #{wcount}\n" 85 | if @cache[:attributes][klass] && !@cache[:attributes][klass].empty? 86 | file.write "Attributes\n" 87 | @cache[:attributes][klass].each do |attr, wcount| 88 | file.write " #{attr}: #{wcount}\n" 89 | end 90 | end 91 | 92 | if @cache[:instance_methods][klass] && !@cache[:instance_methods][klass].empty? 93 | file.write "Instance Methods\n" 94 | @cache[:instance_methods][klass].each do |imeth, wcount| 95 | file.write " #{imeth}: #{wcount}\n" 96 | end 97 | end 98 | 99 | if @cache[:class_methods][klass] && !@cache[:class_methods][klass].empty? 100 | file.write "Class Methods\n" 101 | @cache[:class_methods][klass].each do |cmeth, wcount| 102 | file.write " #{cmeth}: #{wcount}\n" 103 | end 104 | end 105 | 106 | file.write "\r" 107 | end 108 | end 109 | end 110 | 111 | end 112 | end --------------------------------------------------------------------------------