diff --git a/src/code_snippet.cpp b/src/code_snippet.cpp index 6015758..4f65fa4 100644 --- a/src/code_snippet.cpp +++ b/src/code_snippet.cpp @@ -18,6 +18,7 @@ #include "actions.hpp" #include "values.hpp" #include "files.hpp" +#include "input_path.hpp" namespace quickbook { @@ -35,6 +36,7 @@ namespace quickbook , storage(storage) , source_file(source_file) , source_type(source_type) + , error_count(0) { content.start(source_file); } @@ -47,6 +49,7 @@ namespace quickbook void end_snippet(string_iterator first, string_iterator last); void end_snippet_impl(string_iterator); void callout(string_iterator first, string_iterator last); + void end_file(string_iterator, string_iterator); void append_code(string_iterator first, string_iterator last); void close_code(); @@ -97,6 +100,7 @@ namespace quickbook std::vector& storage; file_ptr source_file; char const* const source_type; + int error_count; }; struct python_code_snippet_grammar @@ -118,7 +122,8 @@ namespace quickbook actions_type& actions = self.actions; - start_ = *code_elements; + start_ = (*code_elements) [boost::bind(&actions_type::end_file, &actions, _1, _2)] + ; identifier = (cl::alpha_p | '_') >> *(cl::alnum_p | '_') @@ -222,7 +227,8 @@ namespace quickbook { actions_type& actions = self.actions; - start_ = *code_elements; + start_ = (*code_elements) [boost::bind(&actions_type::end_file, &actions, _1, _2)] + ; identifier = (cl::alpha_p | '_') >> *(cl::alnum_p | '_') @@ -383,8 +389,7 @@ namespace quickbook } assert(info.full); - - return 0; + return a.error_count; } void code_snippet_actions::append_code(string_iterator first, string_iterator last) @@ -408,7 +413,7 @@ namespace quickbook last_code_pos = last; } - + void code_snippet_actions::close_code() { if (!snippet_stack) return; @@ -495,11 +500,47 @@ namespace quickbook void code_snippet_actions::end_snippet(string_iterator first, string_iterator last) { - // TODO: Error? - if(!snippet_stack) return; append_code(first, last); + + if(!snippet_stack) { + if (qbk_version_n >= 106u) { + detail::outerr(source_file, first) + << "Mismatched end snippet." + << std::endl; + ++error_count; + } + else { + detail::outwarn(source_file, first) + << "Mismatched end snippet." + << std::endl; + } + return; + } + end_snippet_impl(first); } + + void code_snippet_actions::end_file(string_iterator, string_iterator pos) + { + append_code(pos, pos); + close_code(); + + while (snippet_stack) { + if (qbk_version_n >= 106u) { + detail::outerr(source_file->path) + << "Unclosed snippet '" << snippet_stack->id << "'" + << std::endl; + ++error_count; + } + else { + detail::outwarn(source_file->path) + << "Unclosed snippet '" << snippet_stack->id << "'" + << std::endl; + } + + end_snippet_impl(pos); + } + } void code_snippet_actions::start_snippet_impl(std::string const& id, string_iterator position) @@ -509,6 +550,8 @@ namespace quickbook void code_snippet_actions::end_snippet_impl(string_iterator position) { + assert(snippet_stack); + boost::shared_ptr snippet = pop_snippet_data(); value callouts = snippet->callouts.release(); diff --git a/src/files.cpp b/src/files.cpp index 474cc0a..de49e34 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -394,29 +394,32 @@ namespace quickbook assert(begin <= x.data->new_file->source.size()); assert(end <= x.data->new_file->source.size()); - std::vector::iterator start = - boost::upper_bound(x.data->new_file->mapped_sections, - begin, mapped_section_pos_cmp()); - assert(start != x.data->new_file->mapped_sections.begin()); - --start; - - std::string::size_type size = data->new_file->source.size(); - - data->new_file->mapped_sections.push_back(mapped_file_section( - start->to_original_pos(begin), size, - start->section_type)); - - for (++start; start != x.data->new_file->mapped_sections.end() && - start->our_pos < end; ++start) + if (begin != end) { + std::vector::iterator start = + boost::upper_bound(x.data->new_file->mapped_sections, + begin, mapped_section_pos_cmp()); + assert(start != x.data->new_file->mapped_sections.begin()); + --start; + + std::string::size_type size = data->new_file->source.size(); + data->new_file->mapped_sections.push_back(mapped_file_section( - start->original_pos, start->our_pos - begin + size, - start->section_type)); - } - - data->new_file->source.append( - x.data->new_file->source.begin() + begin, + start->to_original_pos(begin), size, + start->section_type)); + + for (++start; start != x.data->new_file->mapped_sections.end() && + start->our_pos < end; ++start) + { + data->new_file->mapped_sections.push_back(mapped_file_section( + start->original_pos, start->our_pos - begin + size, + start->section_type)); + } + + data->new_file->source.append( + x.data->new_file->source.begin() + begin, x.data->new_file->source.begin() + end); + } } void mapped_file_builder::unindent_and_add(iterator begin, iterator end) diff --git a/test/snippets/Jamfile.v2 b/test/snippets/Jamfile.v2 index 89f72dd..4dfd0d0 100644 --- a/test/snippets/Jamfile.v2 +++ b/test/snippets/Jamfile.v2 @@ -12,4 +12,7 @@ import quickbook-testing : quickbook-test quickbook-error-test ; test-suite quickbook.test : [ quickbook-test pass_thru ] + [ quickbook-test unbalanced_snippet1-1_5 ] + [ quickbook-error-test unbalanced_snippet1-1_6-fail ] + [ quickbook-error-test unbalanced_snippet2-1_6-fail ] ; diff --git a/test/snippets/unbalanced_snippet1-1_5.gold b/test/snippets/unbalanced_snippet1-1_5.gold new file mode 100644 index 0000000..2089905 --- /dev/null +++ b/test/snippets/unbalanced_snippet1-1_5.gold @@ -0,0 +1,9 @@ + + +
+ Unbalanced snippet fail test 1 + +int main() {} + +
diff --git a/test/snippets/unbalanced_snippet1-1_5.quickbook b/test/snippets/unbalanced_snippet1-1_5.quickbook new file mode 100644 index 0000000..7fdde6a --- /dev/null +++ b/test/snippets/unbalanced_snippet1-1_5.quickbook @@ -0,0 +1,8 @@ +[article Unbalanced snippet fail test 1 +[quickbook 1.5] +] + +[import unbalanced_snippet1.cpp] +[import unbalanced_snippet2.cpp] + +[unclosed] \ No newline at end of file diff --git a/test/snippets/unbalanced_snippet1-1_6-fail.quickbook b/test/snippets/unbalanced_snippet1-1_6-fail.quickbook new file mode 100644 index 0000000..c2fb98e --- /dev/null +++ b/test/snippets/unbalanced_snippet1-1_6-fail.quickbook @@ -0,0 +1,7 @@ +[article Unbalanced snippet fail test 1 +[quickbook 1.6] +] + +[import unbalanced_snippet1.cpp] + +[unclosed] \ No newline at end of file diff --git a/test/snippets/unbalanced_snippet1.cpp b/test/snippets/unbalanced_snippet1.cpp new file mode 100644 index 0000000..ec49a78 --- /dev/null +++ b/test/snippets/unbalanced_snippet1.cpp @@ -0,0 +1,3 @@ +//[unclosed + +int main() {} \ No newline at end of file diff --git a/test/snippets/unbalanced_snippet2-1_6-fail.quickbook b/test/snippets/unbalanced_snippet2-1_6-fail.quickbook new file mode 100644 index 0000000..a06a164 --- /dev/null +++ b/test/snippets/unbalanced_snippet2-1_6-fail.quickbook @@ -0,0 +1,5 @@ +[article Unbalanced snippet fail test 2 +[quickbook 1.6] +] + +[import unbalanced_snippet2.cpp] diff --git a/test/snippets/unbalanced_snippet2.cpp b/test/snippets/unbalanced_snippet2.cpp new file mode 100644 index 0000000..b057517 --- /dev/null +++ b/test/snippets/unbalanced_snippet2.cpp @@ -0,0 +1 @@ +//] \ No newline at end of file