aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/parser.cxx2
-rw-r--r--build2/test/script/parser.cxx66
-rw-r--r--build2/test/script/script6
-rw-r--r--unit-tests/test/script/parser/driver.cxx17
-rw-r--r--unit-tests/test/script/parser/scope.test79
5 files changed, 160 insertions, 10 deletions
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 800d4e9..eb9f463 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -1747,7 +1747,7 @@ namespace build2
ns.insert (ns.end (),
make_move_iterator (rhs.as<names> ().begin ()),
- make_move_iterator (rhs.as<names> ().end ()));
+ make_move_iterator (rhs.as<names> ().end ()));
break;
}
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";
diff --git a/build2/test/script/script b/build2/test/script/script
index 79ada8e..574760e 100644
--- a/build2/test/script/script
+++ b/build2/test/script/script
@@ -216,6 +216,12 @@ namespace build2
private:
friend class parser;
+ bool
+ empty () const
+ {
+ return scopes.empty () && setup_.empty () && tdown_.empty ();
+ }
+
lines setup_;
lines tdown_;
};
diff --git a/unit-tests/test/script/parser/driver.cxx b/unit-tests/test/script/parser/driver.cxx
index 6e3fed5..aad94f9 100644
--- a/unit-tests/test/script/parser/driver.cxx
+++ b/unit-tests/test/script/parser/driver.cxx
@@ -30,13 +30,16 @@ namespace build2
class print_runner: public runner
{
public:
- print_runner (bool scope): scope_ (scope) {}
+ print_runner (bool scope, bool id): scope_ (scope), id_ (id) {}
virtual void
- enter (scope&, const location&) override
+ enter (scope& s, const location&) override
{
if (scope_)
{
+ if (id_ && !s.id_path.empty ()) // Skip empty root scope id.
+ cout << ind_ << ": " << s.id_path.string () << endl;
+
cout << ind_ << "{" << endl;
ind_ += " ";
}
@@ -60,10 +63,11 @@ namespace build2
private:
bool scope_;
+ bool id_;
string ind_;
};
- // Usage: argv[0] [-s] [<testscript-name>]
+ // Usage: argv[0] [-s] [-i] [<testscript-name>]
//
int
main (int argc, char* argv[])
@@ -74,6 +78,7 @@ namespace build2
reset (strings ()); // No command line variables.
bool scope (false);
+ bool id (false);
path name;
for (int i (1); i != argc; ++i)
@@ -82,6 +87,8 @@ namespace build2
if (a == "-s")
scope = true;
+ else if (a == "-i")
+ id = true;
else
{
name = path (move (a));
@@ -92,6 +99,8 @@ namespace build2
if (name.empty ())
name = path ("testscript");
+ assert (!id || scope); // Id can only be printed with scope.
+
try
{
cin.exceptions (istream::failbit | istream::badbit);
@@ -121,7 +130,7 @@ namespace build2
// Parse and run.
//
script s (tt, st, dir_path (work) /= "test-driver");
- print_runner r (scope);
+ print_runner r (scope, id);
parser p;
p.pre_parse (cin, name, s);
diff --git a/unit-tests/test/script/parser/scope.test b/unit-tests/test/script/parser/scope.test
index 593dbb2..a903959 100644
--- a/unit-tests/test/script/parser/scope.test
+++ b/unit-tests/test/script/parser/scope.test
@@ -17,8 +17,16 @@ $* -s <<EOI >>EOO # group-empty
}
EOI
{
- {
- }
+}
+EOO
+
+$* -s <<EOI >>EOO # group-empty-empty
+{
+ {
+ }
+}
+EOI
+{
}
EOO
@@ -40,6 +48,73 @@ EOI
}
EOO
+# Test scope.
+#
+
+$* -s -i <<EOI >>EOO # test-scope
+{
+ cmd
+}
+EOI
+{
+ : 1
+ {
+ cmd
+ }
+}
+EOO
+
+$* -s -i <<EOI >>EOO # test-scope-nested
+{
+ {
+ cmd
+ }
+}
+EOI
+{
+ : 1
+ {
+ cmd
+ }
+}
+EOO
+
+$* -s -i <<EOI >>EOO # test-scope-var
+{
+ x = abc
+ cmd \$x
+}
+EOI
+{
+ : 1
+ {
+ cmd abc
+ }
+}
+EOO
+
+$* -s -i <<EOI >>EOO # test-scope-setup
+{
+ x = abc
+ +setup
+ cmd \$x
+}
+EOI
+{
+ : 1
+ {
+ setup
+ : 1/4
+ {
+ cmd abc
+ }
+ }
+}
+EOO
+
+
+#
+#
$* <:"{x" 2>>EOE != 0 # expected-newline-lcbrace
testscript:1:2: error: expected newline after '{'
EOE