aboutsummaryrefslogtreecommitdiff
path: root/build2/test/script/parser.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-10-26 15:01:54 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:35 +0200
commit43378e3827fd0d17325646c40c76bab9db1da19a (patch)
tree0d68ca5cfb9e58f6afa406a62965a21e82e56a30 /build2/test/script/parser.cxx
parent616690fd06d1c5d05de97b88119dd8d328522df0 (diff)
Handle explicit test scopes
Diffstat (limited to 'build2/test/script/parser.cxx')
-rw-r--r--build2/test/script/parser.cxx66
1 files changed, 63 insertions, 3 deletions
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx
index 25d3636..3043f05 100644
--- a/build2/test/script/parser.cxx
+++ b/build2/test/script/parser.cxx
@@ -114,10 +114,10 @@ namespace build2
// Push group. Use line number as the scope id.
//
+ unique_ptr<group> g (new group (to_string (ll.line), *group_));
+
group* og (group_);
- unique_ptr<group> p (
- group_ = new group (to_string (ll.line), *og));
- og->scopes.push_back (move (p));
+ group_ = g.get ();
group_->start_loc_ = ll;
token e (pre_parse_scope_body ());
@@ -127,6 +127,66 @@ namespace build2
//
group_ = og;
+ // Drop empty scopes.
+ //
+ if (!g->empty ())
+ {
+ // See if this turned out to be an explicit test scope. An
+ // explicit test scope contains a single test, only variable
+ // assignments in setup and nothing in teardown. Plus only the
+ // test or the scope (but not both) can have an explicit id.
+ //
+ // @@ TODO: explicit id.
+ //
+ auto& sc (g->scopes);
+ auto& su (g->setup_);
+ auto& td (g->tdown_);
+
+ test* t;
+ if (sc.size () == 1 &&
+ (t = dynamic_cast<test*> (sc.back ().get ())) != nullptr &&
+ td.empty () &&
+ find_if (
+ su.begin (), su.end (),
+ [] (const line& l)
+ {
+ return l.type != line_type::variable;
+ }) == su.end ())
+ {
+ // It would have been nice to reuse the test object and only
+ // throw aways the group. However, the merged scope should
+ // have id_path/wd_path of the group. So to keep things
+ // simple we are going to throw away both and create a new
+ // test object.
+ //
+ // @@ TODO: decide whose id to use.
+ //
+ unique_ptr<test> m (new test (g->id_path.leaf ().string (),
+ *group_));
+
+ // Merge the lines of the group and the test.
+ //
+ if (su.empty ())
+ m->tests_ = move (t->tests_);
+ else
+ {
+ m->tests_ = move (su); // Should come first.
+ m->tests_.insert (m->tests_.end (),
+ make_move_iterator (t->tests_.begin ()),
+ make_move_iterator (t->tests_.end ()));
+ }
+
+ // Use start/end locations of the outer scope.
+ //
+ m->start_loc_ = g->start_loc_;
+ m->end_loc_ = g->end_loc_;
+
+ group_->scopes.push_back (move (m));
+ }
+ else
+ group_->scopes.push_back (move (g));
+ }
+
if (e.type != type::rcbrace)
fail (e) << "expected '}' at the end of the scope";