From 1754d54da60b5309a497a45c6b8bb5eb5b614b33 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 11 Jun 2019 15:28:56 +0200 Subject: [PATCH 1/2] Don't recreate parsing context for each header --- lib/docurium.rb | 9 +++++---- lib/docurium/docparser.rb | 34 ++++++++++++++++++++++------------ test/parser_test.rb | 12 ++++++++---- 3 files changed, 35 insertions(+), 20 deletions(-) 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..a5155c9a8 100644 --- a/lib/docurium/docparser.rb +++ b/lib/docurium/docparser.rb @@ -31,33 +31,43 @@ 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}) - 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] From 3d5f63015e4cff9a7847987d413e0dad396e7b51 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 11 Jun 2019 15:28:58 +0200 Subject: [PATCH 2/2] Limit clang errors to one Any error when parsing will result in a confused clang parser with missing data --- lib/docurium/docparser.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/docurium/docparser.rb b/lib/docurium/docparser.rb index a5155c9a8..f161b5d44 100644 --- a/lib/docurium/docparser.rb +++ b/lib/docurium/docparser.rb @@ -66,6 +66,7 @@ def parse_file(orig_filename) # Override the path we want to filter by filename = File.join(@tmpdir, orig_filename) args = includes.map { |path| "-I#{path}" } + args << '-ferror-limit=1' tu = Index.new(true, true).parse_translation_unit(filename, args, @unsaved, {:detailed_preprocessing_record => 1})