Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bin/cm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ desc 'Generate HTML documentation'
long_desc 'Generate HTML docs from a Docurium config file'
command :doc do |c|
c.flag :for, :desc => "The version to generate", :multiple => true
c.switch [:n, "dry-run"], :desc => "Dry-run"
c.switch [:d, "debug"], :desc => "Enable debug log"
c.flag "debug-file", :desc => "Enable debug output for header", :multiple => true
c.flag "debug-function", :desc => "Show debug output when processing function", :multiple => true
c.flag "debug-type", :desc => "Show debug output when processing type", :multiple => true
c.action do |global_options,options,args|
file = args.first
Docurium::CLI.doc(file, options)
Expand Down
51 changes: 46 additions & 5 deletions lib/docurium.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'rocco'
require 'docurium/version'
require 'docurium/layout'
require 'docurium/debug'
require 'libdetect'
require 'docurium/docparser'
require 'pp'
Expand All @@ -19,12 +20,13 @@
class Docurium
attr_accessor :branch, :output_dir, :data, :head_data

def initialize(config_file, repo = nil)
def initialize(config_file, cli_options = {}, repo = nil)
raise "You need to specify a config file" if !config_file
raise "You need to specify a valid config file" if !valid_config(config_file)
@sigs = {}
@head_data = nil
@repo = repo || Rugged::Repository.discover(config_file)
@cli_options = cli_options
end

def init_data(version = 'HEAD')
Expand Down Expand Up @@ -192,9 +194,11 @@ def generate_docs(options)

print "Generating documentation [#{i}/#{versions.count}]\r"

output_index.add(:path => "#{version}.json", :oid => sha, :mode => 0100644)
examples.each do |path, id|
output_index.add(:path => path, :oid => id, :mode => 0100644)
unless dry_run?
output_index.add(:path => "#{version}.json", :oid => sha, :mode => 0100644)
examples.each do |path, id|
output_index.add(:path => path, :oid => id, :mode => 0100644)
end
end
end

Expand All @@ -203,6 +207,8 @@ def generate_docs(options)
show_warnings(head_data)
end

return if dry_run?

# We tally the signatures in the order they finished, which is
# arbitrary due to the concurrency, so we need to sort them once
# they've finished.
Expand Down Expand Up @@ -391,7 +397,7 @@ def parse_headers(index, version)
data = init_data(version)
DocParser.with_files(files, :prefix => version) do |parser|
headers.each do |header|
records = parser.parse_file(header)
records = parser.parse_file(header, debug: interesting?(:file, header))
update_globals!(data, records)
end
end
Expand Down Expand Up @@ -466,16 +472,20 @@ def valid_config(file)
def group_functions!(data)
func = {}
data[:functions].each_pair do |key, value|
debug_set interesting?(:function, key)
debug "grouping #{key}: #{value}"
if @options['prefix']
k = key.gsub(@options['prefix'], '')
else
k = key
end
group, rest = k.split('_', 2)
debug "grouped: k: #{k}, group: #{group}, rest: #{rest}"
if group.empty?
puts "empty group for function #{key}"
next
end
debug "grouped: k: #{k}, group: #{group}, rest: #{rest}"
data[:functions][key][:group] = group
func[group] ||= []
func[group] << key
Expand Down Expand Up @@ -521,6 +531,25 @@ def update_globals!(data, recs)
md = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new({}), :no_intra_emphasis => true)
recs.each do |r|

types = %w(function file type).map(&:to_sym)
dbg = false
types.each do |t|
dbg ||= if r[:type] == t and interesting?(t, r[:name])
true
elsif t == :file and interesting?(:file, r[:file])
true
elsif [:struct, :enum].include?(r[:type]) and interesting?(:type, r[:name])
true
else
false
end
end

debug_set dbg

debug "processing record: #{r}"
debug

# initialize filemap for this file
file_map[r[:file]] ||= {
:file => r[:file], :functions => [], :meta => {}, :lines => 0
Expand Down Expand Up @@ -628,6 +657,10 @@ def update_globals!(data, recs)
# Anything else we want to record?
end

debug "processed record: #{r}"
debug

debug_restore
end

data[:files] << file_map.values[0]
Expand Down Expand Up @@ -658,4 +691,12 @@ def write_site(index)
def out(text)
puts text
end

def dry_run?
@cli_options[:dry_run]
end

def interesting?(type, what)
@cli_options['debug'] || (@cli_options["debug-#{type}"] || []).include?(what)
end
end
4 changes: 2 additions & 2 deletions lib/docurium/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ class Docurium
class CLI

def self.doc(idir, options)
doc = Docurium.new(idir)
doc.generate_docs(options)
doc = Docurium.new(idir, options)
doc.generate_docs
end

def self.check(idir, options)
Expand Down
41 changes: 41 additions & 0 deletions lib/docurium/debug.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
$debug_stack = [false]

def debug_enabled
$debug_stack[-1]
end

def debug(str = nil)
puts str if debug_enabled
end

def debug_enable
$debug_stack.push true
end

def debug_silence
$debug_stack.push false
end

def debug_set val
$debug_stack.push val
end

def debug_pass
$debug_stack.push debug_enabled
end

def debug_restore
$debug_stack.pop
end

def with_debug(&block)
debug_enable
block.call
debug_restore
end

def without_debug(&block)
debug_silence
block.call
debug_restore
end
54 changes: 42 additions & 12 deletions lib/docurium/docparser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ def cleanup!

# Entry point for this parser
# Parse `filename` out of the hash `files`
def parse_file(orig_filename)
def parse_file(orig_filename, opts = {})

includes = find_clang_includes + [@tmpdir]

# Override the path we want to filter by
filename = File.join(@tmpdir, orig_filename)
debug_enable if opts[:debug]
debug "parsing #{filename} #{@tmpdir}"
args = includes.map { |path| "-I#{path}" }
args << '-ferror-limit=1'

Expand All @@ -73,12 +75,13 @@ def parse_file(orig_filename)
recs = []

tu.cursor.visit_children do |cursor, parent|
#puts "visiting #{cursor.kind} - #{cursor.spelling}"
location = cursor.location
next :continue if location.file == nil
next :continue unless location.file == filename

#puts "for file #{location.file} #{cursor.kind} #{cursor.spelling} #{cursor.comment.kind} #{location.line}"
loc = "%d:%d-%d:%d" % [cursor.extent.start.line, cursor.extent.start.column, cursor.extent.end.line, cursor.extent.end.column]
debug "#{cursor.location.file}:#{loc} - visiting #{cursor.kind}: #{cursor.spelling}, comment is #{cursor.comment.kind}"

#cursor.visit_children do |c|
# puts " child #{c.kind}, #{c.spelling}, #{c.comment.kind}"
# :continue
Expand All @@ -95,25 +98,38 @@ def parse_file(orig_filename)
:tdef => nil,
}

case cursor.kind
extract = case cursor.kind
when :cursor_function
#puts "have function"
rec.merge! extract_function(cursor)
debug "have function #{cursor.spelling}"
rec.update extract_function(cursor)
when :cursor_enum_decl
rec.merge! extract_enum(cursor)
debug "have enum #{cursor.spelling}"
rec.update extract_enum(cursor)
when :cursor_struct
#puts "raw struct"
rec.merge! extract_struct(cursor)
debug "have struct #{cursor.spelling}"
rec.update extract_struct(cursor)
when :cursor_typedef_decl
rec.merge! extract_typedef(cursor)
debug "have typedef #{cursor.spelling} #{cursor.underlying_type.spelling}"
rec.update extract_typedef(cursor)
else
raise "No idea how to deal with #{cursor.kind}"
end

rec.merge! extract

recs << rec
:continue
end

if debug_enabled
puts "parse_file: parsed #{recs.size} records for #{filename}:"
recs.each do |r|
puts "\t#{r}"
end
end

debug_restore

recs
end

Expand Down Expand Up @@ -187,15 +203,27 @@ def extract_function_args(cursor, cmt)

def extract_subject_desc(comment)
subject = comment.child.text
debug "\t\tsubject: #{subject}"
paras = comment.find_all { |cmt| cmt.kind == :comment_paragraph }.drop(1).map { |p| p.text }
desc = paras.join("\n\n")
debug "\t\tdesc: #{desc}"
return subject, desc
end

def extract_function(cursor)
comment = cursor.comment

#puts "looking at function #{cursor.spelling}, #{cursor.display_name}"
$buggy_functions = %w()
debug_set ($buggy_functions.include? cursor.spelling)
if debug_enabled
puts "\tlooking at function #{cursor.spelling}, #{cursor.display_name}"
puts "\tcomment: #{comment}, #{comment.kind}"
cursor.visit_children do |cur, parent|
puts "\t\tchild: #{cur.spelling}, #{cur.kind}"
:continue
end
end

cmt = extract_function_comment(comment)
args = extract_function_args(cursor, cmt)
#args = args.reject { |arg| arg[:comment].nil? }
Expand All @@ -220,6 +248,7 @@ def extract_function(cursor)
decl = "#{ret[:type]} #{cursor.spelling}(#{argline})"
body = "#{decl};"

debug_restore
#puts cursor.display_name
# Return the format that docurium expects
{
Expand All @@ -238,6 +267,7 @@ def extract_function(cursor)

def extract_function_comment(comment)
subject, desc = extract_subject_desc(comment)
debug "\t\textract_function_comment: #{comment}, #{comment.kind}, #{subject}, #{desc}"

args = {}
(comment.find_all { |cmt| cmt.kind == :comment_param_command }).each do |param|
Expand Down Expand Up @@ -313,7 +343,7 @@ def extract_struct(cursor)
:continue
end

#puts "struct value #{values}"
debug "\tstruct value #{values}"

rec = {
:type => :struct,
Expand Down
2 changes: 1 addition & 1 deletion test/docurium_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def setup
end

@path = File.dirname(__FILE__) + '/fixtures/git2/api.docurium'
@doc = Docurium.new(@path, @repo)
@doc = Docurium.new(@path, {}, @repo)
@data = @doc.parse_headers(index, 'HEAD')
end

Expand Down