diff --git a/pybind11_mkdoc/mkdoc_lib.py b/pybind11_mkdoc/mkdoc_lib.py index 0a553d7..ffc5755 100755 --- a/pybind11_mkdoc/mkdoc_lib.py +++ b/pybind11_mkdoc/mkdoc_lib.py @@ -552,9 +552,23 @@ def extract(filename, node, prefix, output, file_cache): return None +def _report_diagnostics(filename, tu): + """Print clang diagnostics to stderr and fail if any of them is an error.""" + errors = 0 + for diagnostic in tu.diagnostics: + sys.stderr.write(diagnostic.format() + "\n") + if diagnostic.severity >= cindex.Diagnostic.Error: + errors += 1 + if errors: + msg = f"Clang reported {errors} error(s) while parsing {filename}" + raise RuntimeError(msg) + + def _extract_file(filename, parameters): - index = cindex.Index(cindex.conf.lib.clang_createIndex(False, True)) + # Diagnostics are printed by _report_diagnostics, not by libclang itself. + index = cindex.Index(cindex.conf.lib.clang_createIndex(False, False)) tu = index.parse(filename, parameters) + _report_diagnostics(filename, tu) output = [] extract(filename, tu.cursor, "", output, {}) return output diff --git a/tests/cli_test.py b/tests/cli_test.py index 0abf36d..7d86c7f 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -37,3 +37,18 @@ def test_parse_failure_sets_exit_code(tmp_path: Path) -> None: assert result.returncode != 0 assert not tf.exists() + + +def test_missing_include_reports_diagnostics(tmp_path: Path) -> None: + header = tmp_path / "bad_header.h" + header.write_text('#include "does_not_exist.h"\n', encoding="utf-8") + tf = tmp_path / "tmp.h" + result = subprocess.run( + [sys.executable, "-m", "pybind11_mkdoc", "-o", tf, header], + check=False, + capture_output=True, + ) + + assert result.returncode != 0 + assert not tf.exists() + assert "does_not_exist.h" in result.stderr.decode()