1# Copyright (c) Facebook, Inc. and its affiliates. 2# 3# This source code is licensed under the MIT license found in the 4# LICENSE file in the root directory of this source tree. 5 6import os 7import os.path 8 9import libcst.codegen.gen_matcher_classes as matcher_codegen 10import libcst.codegen.gen_type_mapping as type_codegen 11import libcst.codegen.gen_visitor_functions as visitor_codegen 12from libcst.codegen.generate import clean_generated_code, format_file 13from libcst.testing.utils import UnitTest 14 15 16class TestCodegenClean(UnitTest): 17 def test_codegen_clean_visitor_functions(self) -> None: 18 """ 19 Verifies that codegen of visitor functions would not result in a 20 changed file. If this test fails, please run 'tox -e codegen' to 21 generate new files. 22 """ 23 new_code = clean_generated_code("\n".join(visitor_codegen.generated_code)) 24 new_file = os.path.join( 25 os.path.dirname(os.path.abspath(__file__)), "visitor_codegen.py.deleteme" 26 ) 27 with open(new_file, "w") as fp: 28 fp.write(new_code) 29 try: 30 format_file(new_file) 31 except Exception: 32 # We failed to format, but this is probably due to invalid code that 33 # black doesn't like. This test will still fail and report to run codegen. 34 pass 35 with open(new_file, "r") as fp: 36 new_code = fp.read() 37 os.remove(new_file) 38 with open( 39 os.path.join( 40 os.path.dirname(os.path.abspath(__file__)), "../../_typed_visitor.py" 41 ), 42 "r", 43 ) as fp: 44 old_code = fp.read() 45 46 # Now that we've done simple codegen, verify that it matches. 47 self.assertTrue( 48 old_code == new_code, "libcst._typed_visitor needs new codegen!" 49 ) 50 51 def test_codegen_clean_matcher_classes(self) -> None: 52 """ 53 Verifies that codegen of matcher classes would not result in a 54 changed file. If this test fails, please run 'tox -e codegen' to 55 generate new files. 56 """ 57 new_code = clean_generated_code("\n".join(matcher_codegen.generated_code)) 58 new_file = os.path.join( 59 os.path.dirname(os.path.abspath(__file__)), "matcher_codegen.py.deleteme" 60 ) 61 with open(new_file, "w") as fp: 62 fp.write(new_code) 63 try: 64 format_file(new_file) 65 except Exception: 66 # We failed to format, but this is probably due to invalid code that 67 # black doesn't like. This test will still fail and report to run codegen. 68 pass 69 with open(new_file, "r") as fp: 70 new_code = fp.read() 71 os.remove(new_file) 72 with open( 73 os.path.join( 74 os.path.dirname(os.path.abspath(__file__)), "../../matchers/__init__.py" 75 ), 76 "r", 77 ) as fp: 78 old_code = fp.read() 79 80 # Now that we've done simple codegen, verify that it matches. 81 self.assertTrue( 82 old_code == new_code, "libcst.matchers.__init__ needs new codegen!" 83 ) 84 85 def test_codegen_clean_return_types(self) -> None: 86 """ 87 Verifies that codegen of return types would not result in a 88 changed file. If this test fails, please run 'tox -e codegen' to 89 generate new files. 90 """ 91 new_code = clean_generated_code("\n".join(type_codegen.generated_code)) 92 new_file = os.path.join( 93 os.path.dirname(os.path.abspath(__file__)), "type_codegen.py.deleteme" 94 ) 95 with open(new_file, "w") as fp: 96 fp.write(new_code) 97 try: 98 format_file(new_file) 99 except Exception: 100 # We failed to format, but this is probably due to invalid code that 101 # black doesn't like. This test will still fail and report to run codegen. 102 pass 103 with open(new_file, "r") as fp: 104 new_code = fp.read() 105 os.remove(new_file) 106 with open( 107 os.path.join( 108 os.path.dirname(os.path.abspath(__file__)), 109 "../../matchers/_return_types.py", 110 ), 111 "r", 112 ) as fp: 113 old_code = fp.read() 114 115 # Now that we've done simple codegen, verify that it matches. 116 self.assertTrue( 117 old_code == new_code, "libcst.matchers._return_types needs new codegen!" 118 ) 119