Merge "Update the parser to parse validations" into main
diff --git a/vndk/tools/sourcedr/ninja/ninja.py b/vndk/tools/sourcedr/ninja/ninja.py
index 17291ec..5ddc72b 100755
--- a/vndk/tools/sourcedr/ninja/ninja.py
+++ b/vndk/tools/sourcedr/ninja/ninja.py
@@ -207,7 +207,7 @@
 class Build(object):
     __slots__ = ('explicit_outs', 'implicit_outs', 'rule', 'explicit_ins',
                  'implicit_ins', 'prerequisites', 'bindings',
-                 'depfile_implicit_ins')
+                 'depfile_implicit_ins', 'validations')
 
 
 class Rule(object):
@@ -236,13 +236,14 @@
     ESC_NEWLINE = 4
     IDENT = 5
     PIPE2 = 6
-    PIPE = 7
-    COLON = 8
-    ASSIGN = 9
+    PIPEAT = 7
+    PIPE = 8
+    COLON = 9
+    ASSIGN = 10
 
     # Non-trivial tokens
-    PATH = 10
-    STRING = 11
+    PATH = 11
+    STRING = 12
 
 
 class TokenMatcher(object):
@@ -340,6 +341,7 @@
         (TK.ESC_NEWLINE, r'\$[\r\n]'),
         (TK.IDENT, r'[\w_.-]+'),
         (TK.PIPE2, r'\|\|'),
+        (TK.PIPEAT, r'\|@'),
         (TK.PIPE, r'\|'),
         (TK.COLON, r':'),
         (TK.ASSIGN, r'='),
@@ -709,13 +711,13 @@
 
         # Parse explicit ins
         explicit_ins = self._parse_path_list(
-                {TK.PIPE, TK.PIPE2, TK.NEWLINE, TK.EOF})
+                {TK.PIPE, TK.PIPE2, TK.PIPEAT, TK.NEWLINE, TK.EOF})
 
         # Parse implicit ins
         token = self._lexer.peek()
         if token.kind == TK.PIPE:
             self._lexer.lex()
-            implicit_ins = self._parse_path_list({TK.PIPE2, TK.NEWLINE, TK.EOF})
+            implicit_ins = self._parse_path_list({TK.PIPE2, TK.PIPEAT, TK.NEWLINE, TK.EOF})
         else:
             implicit_ins = tuple()
 
@@ -723,10 +725,18 @@
         token = self._lexer.peek()
         if token.kind == TK.PIPE2:
             self._lexer.lex()
-            prerequisites = self._parse_path_list({TK.NEWLINE, TK.EOF})
+            prerequisites = self._parse_path_list({TK.PIPEAT, TK.NEWLINE, TK.EOF})
         else:
             prerequisites = tuple()
 
+        # parse validations
+        token = self._lexer.peek()
+        if token.kind == TK.PIPEAT:
+            self._lexer.lex()
+            validations = self._parse_path_list({TK.NEWLINE, TK.EOF})
+        else:
+            validations = tuple()
+
         self._lexer.lex_match({TK.NEWLINE, TK.EOF})
 
         # Parse local bindings
@@ -746,6 +756,7 @@
         build.explicit_ins = eval_path_strings(explicit_ins, env)
         build.implicit_ins = eval_path_strings(implicit_ins, env)
         build.prerequisites = eval_path_strings(prerequisites, env)
+        build.validations = eval_path_strings(validations, env)
         build.depfile_implicit_ins = tuple()
 
         self._builds.append(build)
diff --git a/vndk/tools/sourcedr/ninja/tests/test_ninja.py b/vndk/tools/sourcedr/ninja/tests/test_ninja.py
index 0c0560c..3534b3d 100755
--- a/vndk/tools/sourcedr/ninja/tests/test_ninja.py
+++ b/vndk/tools/sourcedr/ninja/tests/test_ninja.py
@@ -346,6 +346,11 @@
         tok = lexer.lex()
         self.assertEqual(ninja.TK.PIPE2, tok.kind)
 
+    def test_lex_pipeat(self):
+        lexer = ninja.Lexer(['|@'])
+        tok = lexer.lex()
+        self.assertEqual(ninja.TK.PIPEAT, tok.kind)
+
     def test_lex_non_trivial(self):
         lexer = ninja.Lexer(['$name'])
         with self.assertRaises(ninja.ParseError):
@@ -537,6 +542,8 @@
         self.assertEqual('implicit_in2', build.implicit_ins[1])
         self.assertEqual('order_only1', build.prerequisites[0])
         self.assertEqual('order_only2', build.prerequisites[1])
+        self.assertEqual('validation1', build.validations[0])
+        self.assertEqual('validation2', build.validations[1])
 
         self.assertEqual(('t', '1',), build.bindings['a'])
         self.assertEqual(('t', '2',), build.bindings['b'])
diff --git a/vndk/tools/sourcedr/ninja/tests/testdata/build.ninja b/vndk/tools/sourcedr/ninja/tests/testdata/build.ninja
index 748899b..08b62e1 100644
--- a/vndk/tools/sourcedr/ninja/tests/testdata/build.ninja
+++ b/vndk/tools/sourcedr/ninja/tests/testdata/build.ninja
@@ -1,3 +1,3 @@
-build explicit_out1 explicit_out2 | implicit_out1 implicit_out2 : phony explicit_in1 explicit_in2 | implicit_in1 implicit_in2 || order_only1 order_only2
+build explicit_out1 explicit_out2 | implicit_out1 implicit_out2 : phony explicit_in1 explicit_in2 | implicit_in1 implicit_in2 || order_only1 order_only2 |@ validation1 validation2
   a = 1
   b = 2