diff --git a/lib/docurium.rb b/lib/docurium.rb index 0974e0e32..c43c81076 100644 --- a/lib/docurium.rb +++ b/lib/docurium.rb @@ -292,10 +292,11 @@ def parse_headers(index, version) end data = init_data(version) - parser = DocParser.new - headers.each do |header| - records = parser.parse_file(header, files) - update_globals!(data, records) + DocParser.with_files(files, :prefix => version) do |parser| + headers.each do |header| + records = parser.parse_file(header) + update_globals!(data, records) + end end data[:groups] = group_functions!(data) diff --git a/lib/docurium/docparser.rb b/lib/docurium/docparser.rb index 4d04df134..f161b5d44 100644 --- a/lib/docurium/docparser.rb +++ b/lib/docurium/docparser.rb @@ -31,33 +31,44 @@ def find_clang_includes end end - # Entry point for this parser - # Parse `filename` out of the hash `files` - def parse_file(orig_filename, files) + def self.with_files(files, opts = {}) + parser = self.new(files, opts) + yield parser + parser.cleanup! + end + def initialize(files, opts = {}) # unfortunately Clang wants unsaved files to exist on disk, so # we need to create at least empty files for each unsaved file # we're given. - tmpdir = Dir.mktmpdir() - - unsaved = files.map do |name, contents| - full_path = File.join(tmpdir, name) + prefix = (opts[:prefix] ? opts[:prefix] + "-" : nil) + @tmpdir = Dir.mktmpdir(prefix) + @unsaved = files.map do |name, contents| + full_path = File.join(@tmpdir, name) dirname = File.dirname(full_path) FileUtils.mkdir_p(dirname) unless Dir.exist? dirname File.new(full_path, File::CREAT).close() - UnsavedFile.new(full_path, contents) end + end + + def cleanup! + FileUtils.remove_entry(@tmpdir) + end + + # Entry point for this parser + # Parse `filename` out of the hash `files` + def parse_file(orig_filename) - includes = find_clang_includes + [tmpdir] + includes = find_clang_includes + [@tmpdir] # Override the path we want to filter by - filename = File.join(tmpdir, orig_filename) + filename = File.join(@tmpdir, orig_filename) args = includes.map { |path| "-I#{path}" } - tu = Index.new(true, true).parse_translation_unit(filename, args, unsaved, {:detailed_preprocessing_record => 1}) + args << '-ferror-limit=1' - FileUtils.remove_entry(tmpdir) + tu = Index.new(true, true).parse_translation_unit(filename, args, @unsaved, {:detailed_preprocessing_record => 1}) recs = [] diff --git a/test/parser_test.rb b/test/parser_test.rb index 69611920f..72793fac9 100644 --- a/test/parser_test.rb +++ b/test/parser_test.rb @@ -4,13 +4,17 @@ class ParserTest < Minitest::Test - def setup - @parser = Docurium::DocParser.new + def teardown + @parser.cleanup! if @parser end # e.g. parse('git2/refs.h') + # contents is either a string (the contents of "path") + # or a hash of paths => contents def parse(path, contents) - @parser.parse_file(path, [[path, contents]]) + contents = [[path, contents]] if contents.is_a? String + @parser = Docurium::DocParser.new(contents) + @parser.parse_file(path) end def test_single_function @@ -122,7 +126,7 @@ def test_parsing_with_extern GIT_EXTERN(int) some_public_function(int val); EOF - actual = @parser.parse_file(name_b, [[name_a, contents_a], [name_b, contents_b]]) + actual = parse(name_b, [[name_a, contents_a], [name_b, contents_b]]) # "Fix" the path so we remove the temp dir actual[0][:file] = File.split(actual[0][:file])[-1]