diff --git a/README.rst b/README.rst index c0b5ae3a..74e6b415 100644 --- a/README.rst +++ b/README.rst @@ -1,10 +1,10 @@ C/C++ Linting Package ===================== -.. image:: https://img.shields.io/github/v/release/cpp-linter/cpp-linter?style=plastic +.. image:: https://img.shields.io/github/v/release/cpp-linter/cpp-linter :alt: Latest Version :target: https://github.com/cpp-linter/cpp-linter/releases -.. image:: https://img.shields.io/github/license/cpp-linter/cpp-linter?label=license&logo=github&style=plastic +.. image:: https://img.shields.io/github/license/cpp-linter/cpp-linter?label=license&logo=github :alt: License :target: https://github.com/cpp-linter/cpp-linter/blob/main/LICENSE .. image:: https://codecov.io/gh/cpp-linter/cpp-linter/branch/main/graph/badge.svg?token=0814O9WHQU @@ -13,6 +13,9 @@ C/C++ Linting Package .. image:: https://github.com/cpp-linter/cpp-linter/actions/workflows/build-docs.yml/badge.svg :alt: Docs :target: https://cpp-linter.github.io/cpp-linter +.. image:: https://img.shields.io/pypi/dw/cpp-linter?color=dark-green&label=PyPI%20Downloads&logo=python&logoColor=white + :target: https://pepy.tech/project/cpp-linter + :alt: PyPI - Downloads A Python package for linting C/C++ code with clang-tidy and/or clang-format to collect feedback provided in the form of thread comments and/or file annotations. diff --git a/cpp_linter/run.py b/cpp_linter/run.py index d98281e1..2a0f212f 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -124,7 +124,7 @@ installed (if using a custom install location). All paths specified here are converted to absolute. -Default is """ +Default is """, ) assert arg.help is not None arg.help += "a blank string." if not arg.default else f"``{arg.default}``." @@ -237,6 +237,23 @@ Defaults to ``%(default)s``.""", ) +cli_arg_parser.add_argument( + "-x", + "--extra-arg", + default=[], + action="append", + help="""A string of extra arguments passed to clang-tidy for use as +compiler arguments. This can be specified more than once for each +additional argument. Recommend using quotes around the value and +avoid using spaces between name and value (use ``=`` instead): + +.. code-block:: shell + + cpp-linter --extra-arg="-std=c++17" --extra-arg="-Wall" + +Defaults to ``'%(default)s'``. +""", +) def set_exit_code(override: int = None) -> int: @@ -477,6 +494,7 @@ def run_clang_tidy( lines_changed_only: int, database: str, repo_root: str, + extra_args: List[str], ) -> None: """Run clang-tidy on a certain file. @@ -489,6 +507,23 @@ def run_clang_tidy( diff info. :param database: The path to the compilation database. :param repo_root: The path to the repository root folder. + :param extra_args: A list of extra arguments used by clang-tidy as compiler + arguments. + + .. note:: + If the list is only 1 item long and there is a space in the first item, + then the list is reformed from splitting the first item by whitespace + characters. + + .. code-block:: shell + + cpp-linter --extra-arg="-std=c++14 -Wall" + + is equivalent to + + .. code-block:: shell + + cpp-linter --extra-arg=-std=c++14 --extra-arg=-Wall """ if checks == "-*": # if all checks are disabled, then clang-tidy is skipped # clear the clang-tidy output file and exit function @@ -511,6 +546,10 @@ def run_clang_tidy( line_ranges = dict(name=filename, lines=file_obj["line_filter"][ranges]) logger.info("line_filter = %s", json.dumps([line_ranges])) cmds.append(f"--line-filter={json.dumps([line_ranges])}") + if len(extra_args) == 1 and " " in extra_args[0]: + extra_args = extra_args[0].split() + for extra_arg in extra_args: + cmds.append(f"--extra-arg={extra_arg}") cmds.append(filename) # clear yml file's content before running clang-tidy Path("clang_tidy_output.yml").write_bytes(b"") @@ -623,6 +662,7 @@ def capture_clang_tools_output( lines_changed_only: int, database: str, repo_root: str, + extra_args: List[str], ): """Execute and capture all output from clang-tidy and clang-format. This aggregates results in the :attr:`~cpp_linter.Globals.OUTPUT`. @@ -636,6 +676,8 @@ def capture_clang_tools_output( diff info. :param database: The path to the compilation database. :param repo_root: The path to the repository root folder. + :param extra_args: A list of extra arguments used by clang-tidy as compiler + arguments. """ # temporary cache of parsed notifications for use in log commands tidy_notes: List[TidyNotification] = [] @@ -643,7 +685,14 @@ def capture_clang_tools_output( filename = cast(str, file["filename"]) start_log_group(f"Performing checkup on {filename}") run_clang_tidy( - filename, file, version, checks, lines_changed_only, database, repo_root + filename, + file, + version, + checks, + lines_changed_only, + database, + repo_root, + extra_args, ) run_clang_format(filename, file, version, style, lines_changed_only) end_log_group() @@ -962,6 +1011,7 @@ def main(): args.lines_changed_only, args.database, args.repo_root, + args.extra_arg, ) start_log_group("Posting comment(s)") diff --git a/docs/_static/extra_css.css b/docs/_static/extra_css.css index 8e2a15ed..9a20a75f 100644 --- a/docs/_static/extra_css.css +++ b/docs/_static/extra_css.css @@ -5,6 +5,7 @@ thead { } .md-header, +.md-tabs, .md-nav--primary .md-nav__title[for="__drawer"] { background-color: #4051b5; } diff --git a/pyproject.toml b/pyproject.toml index 7190417c..2642715f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=45", "setuptools-scm"] +requires = ["setuptools>=61", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] @@ -440,7 +440,23 @@ confidence = ["HIGH", "CONTROL_FLOW", "INFERENCE", "INFERENCE_FAILURE", "UNDEFIN # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use "--disable=all --enable=classes # --disable=W". -disable = ["raw-checker-failed", "bad-inline-option", "locally-disabled", "file-ignored", "suppressed-message", "useless-suppression", "deprecated-pragma", "use-symbolic-message-instead", "invalid-sequence-index", "anomalous-backslash-in-string", "too-few-public-methods", "consider-using-f-string", "subprocess-run-check"] +disable = [ + "raw-checker-failed", + "bad-inline-option", + "locally-disabled", + "file-ignored", + "suppressed-message", + "useless-suppression", + "deprecated-pragma", + "use-symbolic-message-instead", + "invalid-sequence-index", + "anomalous-backslash-in-string", + "too-few-public-methods", + "consider-using-f-string", + "subprocess-run-check", + "missing-timeout", + "too-many-lines" +] # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/tests/capture_tools_output/test_database_path.py b/tests/capture_tools_output/test_database_path.py index 3bafa661..1b7eeeb5 100644 --- a/tests/capture_tools_output/test_database_path.py +++ b/tests/capture_tools_output/test_database_path.py @@ -48,6 +48,7 @@ def test_db_detection( lines_changed_only=0, # analyze complete file database=database, repo_root=rel_root, + extra_args=[], ) matched_args = [] for record in caplog.records: diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py index c7467fa3..bb45f1c7 100644 --- a/tests/capture_tools_output/test_tools_output.py +++ b/tests/capture_tools_output/test_tools_output.py @@ -113,6 +113,7 @@ def test_format_annotations( lines_changed_only=lines_changed_only, database="", repo_root="", + extra_args=[], ) assert "Output from `clang-tidy`" not in cpp_linter.Globals.OUTPUT caplog.set_level(logging.INFO, logger=log_commander.name) @@ -162,6 +163,7 @@ def test_tidy_annotations( lines_changed_only=lines_changed_only, database="", repo_root="", + extra_args=[], ) assert "Run `clang-format` on the following files" not in cpp_linter.Globals.OUTPUT caplog.set_level(logging.INFO, logger=log_commander.name) @@ -195,6 +197,7 @@ def test_diff_comment(lines_changed_only: int): lines_changed_only=lines_changed_only, database="", repo_root="", + extra_args=[], ) diff_comments = list_diff_comments(lines_changed_only) # output = Path(__file__).parent / "diff_comments.json" diff --git a/tests/test_cli_args.py b/tests/test_cli_args.py index 40158777..a74255a3 100644 --- a/tests/test_cli_args.py +++ b/tests/test_cli_args.py @@ -36,6 +36,7 @@ class Args: files_changed_only: bool = False thread_comments: bool = False file_annotations: bool = True + extra_arg: List[str] = [] def test_defaults(): @@ -62,6 +63,8 @@ def test_defaults(): ("files-changed-only", "True", "files_changed_only", True), ("thread-comments", "True", "thread_comments", True), ("file-annotations", "False", "file_annotations", False), + ("extra-arg", "-std=c++17", "extra_arg", ["-std=c++17"]), + ("extra-arg", '"-std=c++17 -Wall"', "extra_arg", ['"-std=c++17 -Wall"']), ], ) def test_arg_parser(