diff --git a/src/codemodder/codemodder.py b/src/codemodder/codemodder.py index f2b50f31..4c7c43f9 100644 --- a/src/codemodder/codemodder.py +++ b/src/codemodder/codemodder.py @@ -97,13 +97,19 @@ def analyze_files( line_include, sarif_for_file, ) - - apply_codemod_to_file( - execution_context, - file_context, - codemod, - source_tree, - ) + try: + apply_codemod_to_file( + execution_context, + file_context, + codemod, + source_tree, + ) + except Exception: + execution_context.add_failure(codemod.id, file_path) + logger.exception( + "error transforming file %s with codemod %s", file_path, codemod.id + ) + continue if failures := execution_context.get_failures(codemod.id): logger.info("failed:") diff --git a/tests/test_codemodder.py b/tests/test_codemodder.py index 137bd65c..2426bc3a 100644 --- a/tests/test_codemodder.py +++ b/tests/test_codemodder.py @@ -25,9 +25,7 @@ def test_no_files_matched(self, error_log, mock_parse): mock_parse.assert_not_called() - @mock.patch("libcst.parse_module", side_effect=Exception) - @mock.patch("codemodder.codemodder.report_default") - def test_cst_parsing_fails(self, mock_reporting, mock_parse): + def run_and_assert_failures(self, mock_reporting, mock_parse): args = [ "tests/samples/", "--output", @@ -57,6 +55,16 @@ def test_cst_parsing_fails(self, mock_reporting, mock_parse): "tests/samples/unverified_request.py", ] + @mock.patch("libcst.parse_module", side_effect=Exception) + @mock.patch("codemodder.codemodder.report_default") + def test_cst_parsing_fails(self, mock_reporting, mock_parse): + self.run_and_assert_failures(mock_reporting, mock_parse) + + @mock.patch("codemodder.codemodder.apply_codemod_to_file", side_effect=Exception) + @mock.patch("codemodder.codemodder.report_default") + def test_transform_fails(self, mock_reporting, mock_parse): + self.run_and_assert_failures(mock_reporting, mock_parse) + @mock.patch("codemodder.codemodder.update_code") @mock.patch("codemodder.codemods.base_codemod.semgrep_run", side_effect=semgrep_run) def test_dry_run(self, _, mock_update_code):