[gen_ast_dump_json_test.py] Allow updating multiple files in one go
authorAlex Richardson <Alexander.Richardson@cl.cam.ac.uk>
Tue, 12 Nov 2019 12:00:51 +0000 (12:00 +0000)
committerAlex Richardson <Alexander.Richardson@cl.cam.ac.uk>
Fri, 15 Nov 2019 12:52:56 +0000 (12:52 +0000)
With this change it is possible to update all JSON dump tests using the
following command:
python $LLVM_BINDIR/gen_ast_dump_json_test.py --update --source $LLVM_SRC/clang/test/AST/*-json.*

See https://reviews.llvm.org/D70119

clang/test/AST/gen_ast_dump_json_test.py

index 699aaf0..3a40646 100644 (file)
@@ -68,8 +68,9 @@ def main():
     parser = argparse.ArgumentParser()
     parser.add_argument("--clang", help="The clang binary (could be a relative or absolute path)",
                         action="store", default=default_clang_path())
-    parser.add_argument("--source", help="the source file. Command used to generate the json will be of the format <clang> -cc1 -ast-dump=json <opts> <source>",
-                        action="store", required=True)
+    parser.add_argument("--source", help="the source file(s). Without --update, the command used to generate the JSON "
+                                         "will be of the format <clang> -cc1 -ast-dump=json <opts> <source>",
+                        action="store", nargs=argparse.ONE_OR_MORE, required=True)
     parser.add_argument("--filters", help="comma separated list of AST filters. Ex: --filters=TypedefDecl,BuiltinType",
                         action="store", default='')
     update_or_generate_group = parser.add_mutually_exclusive_group()
@@ -81,23 +82,29 @@ def main():
     args = parser.parse_args()
 
     if not args.source:
-        print("Specify the source file to give to clang.")
-        return -1
+        sys.exit("Specify the source file to give to clang.")
 
     clang_binary = os.path.abspath(args.clang)
     if not os.path.isfile(clang_binary):
-        print("clang binary specified not present.")
-        return -1
+        sys.exit("clang binary specified not present.")
+
+    for src in args.source:
+        process_file(src, clang_binary, cmdline_filters=args.filters,
+                     cmdline_opts=args.opts, do_update=args.update,
+                     force_update=args.update_manual)
+
 
+def process_file(source_file, clang_binary, cmdline_filters, cmdline_opts,
+                 do_update, force_update):
     note_firstline = "// NOTE: CHECK lines have been autogenerated by " \
                      "gen_ast_dump_json_test.py"
     filters_line_prefix = "// using --filters="
     note = note_firstline
 
     cmd = [clang_binary, "-cc1"]
-    if args.update:
+    if do_update:
         # When updating the first line of the test must be a RUN: line
-        with open(args.source, "r") as srcf:
+        with open(source_file, "r") as srcf:
             first_line = srcf.readline()
             found_autogenerated_line = False
             filters_line = None
@@ -110,12 +117,13 @@ def main():
                 if line.startswith(note_firstline):
                     found_autogenerated_line = True
                     # print("Found autogenerated disclaimer at line", i + 1)
-        if not found_autogenerated_line and not args.update_manual:
-            print("Not updating", args.source, "since it is not autogenerated.")
-            sys.exit(0)
-        if not args.filters and filters_line:
-            args.filters = filters_line
-            print("Inferred filters as '" + args.filters + "'")
+        if not found_autogenerated_line and not force_update:
+            print("Not updating", source_file, "since it is not autogenerated.",
+                  file=sys.stderr)
+            return
+        if not cmdline_filters and filters_line:
+            cmdline_filters = filters_line
+            print("Inferred filters as '" + cmdline_filters + "'")
 
         if "RUN: %clang_cc1 " not in first_line:
             sys.exit("When using --update the first line of the input file must contain RUN: %clang_cc1")
@@ -133,19 +141,18 @@ def main():
             sys.exit("ERROR: RUN: line does not contain %s")
         options.remove("%s")
     else:
-        options = args.opts.split()
+        options = cmdline_opts.split()
         options.append("-ast-dump=json")
     cmd.extend(options)
     using_ast_dump_filter = any('ast-dump-filter' in arg for arg in cmd)
-    cmd.append(args.source)
+    cmd.append(source_file)
     print("Will run", cmd)
     filters = set()
-    if args.filters:
-        note += "\n" + filters_line_prefix + args.filters
-        filters = set(args.filters.split(','))
+    if cmdline_filters:
+        note += "\n" + filters_line_prefix + cmdline_filters
+        filters = set(cmdline_filters.split(','))
     print("Will use the following filters:", filters)
 
-
     try:
         json_str = subprocess.check_output(cmd)
     except Exception as ex:
@@ -174,7 +181,7 @@ def main():
             filter_json(j, filters, out_asts)
         
     with tempfile.NamedTemporaryFile("w") as f:
-        with open(args.source, "r") as srcf:
+        with open(source_file, "r") as srcf:
             for line in srcf.readlines():
                 # copy up to the note:
                 if line.rstrip() == note_firstline:
@@ -194,15 +201,16 @@ def main():
                     
             f.write(out_str)
         f.flush()
-        if args.update:
-            print("Updating json appended source file to %s." %  args.source)
-            copyfile(f.name, args.source)
+        if do_update:
+            print("Updating json appended source file to %s." % source_file)
+            copyfile(f.name, source_file)
         else:
-            partition = args.source.rpartition('.')
+            partition = source_file.rpartition('.')
             dest_path = '%s-json%s%s' % (partition[0], partition[1], partition[2])
             print("Writing json appended source file to %s." % dest_path)
             copyfile(f.name, dest_path)
     return 0
-        
+
+
 if __name__ == '__main__':
     main()