Code Monkey home page Code Monkey logo

pre-commit-hooks's Introduction

pre-commit hooks

Ubuntu Build Macos Build Windows Build

This is a pre-commit hooks repo that integrates two C/C++ code formatters:

clang-format, uncrustify,

and five C/C++ static code analyzers:

clang-tidy, oclint, cppcheck, cpplint, include-what-you-use

This repo's hooks do more than passthrough arguments to provide these features:

  • Relay correct pass/fail to pre-commit, even when some commands exit 0 when they should not. Some versions of oclint, clang-tidy, and cppcheck have this behavior.
  • Honor -- arguments, which pre-commit has problems with
  • Optionally enforce a command version so your team gets code formatted/analyzed the same way
  • Formatters clang-format and uncrustify will error with diffs of what has changed

Example Usage

With this err.c

#include <stdio.h>
int main(){int i;return;}

and using this .pre-commit-config.yaml:

fail_fast: false
repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: master
    hooks:
      - id: clang-format
        args: [--style=Google]
      - id: clang-tidy
      - id: oclint
      - id: uncrustify
      - id: cppcheck
      - id: cpplint
      - id: include-what-you-use

All seven linters should fail on commit with these messages. Full text is at media/all_failed.txt.

clang-format error (indentation)
clang-format.............................................................Failed
- hook id: clang-format
- exit code: 1

err.c
====================
--- original

+++ formatted

@@ -1,3 +1,6 @@

 #include <stdio.h>
-int main(){int i;return;}
+int main() {
+  int i;
+  return;
+}

clang-tidy error (non-void main should return a value)
clang-tidy...............................................................Failed
- hook id: clang-tidy
- exit code: 1

/tmp/temp/err.c:2:18: error: non-void function 'main' should return a value [clang-diagnostic-return-type]
int main(){int i;return;}
                 ^
1 error generated.
Error while processing /tmp/temp/err.c.
Found compiler error(s).

oclint error (non-void main should return a value)
oclint...................................................................Failed
- hook id: oclint
- exit code: 6

Compiler Errors:
(please be aware that these errors will prevent OCLint from analyzing this source code)

/tmp/temp/err.c:2:18: non-void function 'main' should return a value

Clang Static Analyzer Results:

/tmp/temp/err.c:2:18: non-void function 'main' should return a value


OCLint Report

Summary: TotalFiles=0 FilesWithViolations=0 P1=0 P2=0 P3=0


[OCLint (https://oclint.org) v21.05]

uncrustify error (indentation)
uncrustify...............................................................Failed
- hook id: uncrustify
- exit code: 1

err.c
====================
--- original

+++ formatted

@@ -1,3 +1,5 @@

 #include <stdio.h>
-int main(){int i;return;}
+int main(){
+  int i; return;
+}

cppcheck error (unused variable i)
cppcheck.................................................................Failed
- hook id: cppcheck
- exit code: 1

err.c:2:16: style: Unused variable: i [unusedVariable]
int main(){int i;return;}
               ^

cpplint error (no copyright message, bad whitespace)
cpplint..................................................................Failed
- hook id: cpplint
- exit code: 1

Done processing err.c
Total errors found: 4
err.c:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
err.c:2:  More than one command on the same line  [whitespace/newline] [0]
err.c:2:  Missing space after ;  [whitespace/semicolon] [3]
err.c:2:  Missing space before {  [whitespace/braces] [5]

include-what-you-use error (remove unused #include )
include-what-you-use.....................................................Failed
- hook id: include-what-you-use
- exit code: 3

err.c:2:18: error: non-void function 'main' should return a value [-Wreturn-type]
int main(){int i;return;}
                 ^

err.c should add these lines:

err.c should remove these lines:
- #include <stdio.h>  // lines 1-1

The full include-list for err.c:
---

Note that for your config yaml, you can supply your own args or remove the args line entirely, depending on your use case.

You can also clone this repo and then run the test_repo to see all of the linters at work to produce this output:

git clone https://github.com/pocc/pre-commit-hooks
cp -r pre-commit-hooks/tests/test_repo .
cd test_repo
git init
git add .
pre-commit run

Note that we are copying the test_repo outside of the pre-commit-hooks repo so that pre-commit doesn't get confused by nested github repositories.

Using this repo

Special flags in this repo

There are 2 flags, --version and --no-diff that can be added to args: for a pre-commit hook. They will be removed and not be passed on to the command.

Some linters change behavior between versions. To enforce a linter version 8.0.0, for example, add --version=8.0.0 to args: for that linter. Note that this is a pre-commit hook arg and will be filtered before args are passed to the linter.

You can add --no-diff to the args: for clang-format and uncrustify if you would like there to be no diff output for these commands.

Default Options

These options are automatically added to enable all errors or are required.

  • oclint: ["-enable-global-analysis", "-enable-clang-static-analyzer", "-max-priority-3", "0"]
  • uncrustify: ["-c", "defaults.cfg", "-q"] (options added, and a defaults.cfg generated, if -c is missing)
  • cppcheck: ["-q" , "--error-exitcode=1", "--enable=all", "--suppress=unmatchedSuppression", "--suppress=missingIncludeSystem", "--suppress=unusedFunction"] (See #30)
  • cpplint: ["--verbose=0"]

If you supply any of these options in args:, your options will override the above defaults (use -<flag>=<option> if possible when overriding).

Compilation Database

clang-tidy and oclint both expect a compilation database. Both of the hooks for them will ignore the error for not having one.

You can generate with one cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON <dir> if you have a cmake-based project.

Information about the Commands

Python3.6+ is required to use these hooks as all 5 invoking scripts are written in it. As this is also the minimum version of pre-commit, this should not be an issue.

Installation

Use these commands to install some or all of the linters used in this project:

  • Linux
    • brew install llvm uncrustify cppcheck include-what-you-use [1] [2]
    • oclint: See note below for installation [3]
  • MacOS
    • brew install llvm uncrustify cppcheck include-what-you-use oclint
  • Windows
    • choco install llvm uncrustify cppcheck inlcude-what-you-use
  • Cross-platform
    • pip install cpplint
    • pipx install clang-format [4]

[1]: llvm includes tools like clang-format and clang-tidy.

[2]: While it's possible to use other package managers to install these utilities on Linux, I recommend using brew to avoid dependency issues between llvm and linters that use it, such as include-what-you-use.

[3]: You can install on MacOS with brew install oclint. Oclint's github page also provides compiled binary packages (and zip of source code to compile) for Macos/Linux: releases. oclint is not available on windows.

[4]: This will download the latest version. Versions from 10.0.1 and up are supported. To pin to a specific version like 13.0.0, use pipx install clang-format==13.0.0. Check out the clang-format-wheel repository for information on how to download the clang-format binary as part of a CI pre-commit build.

Hook Info

Hook Info Type Languages
clang-format Formatter C, C++, ObjC, ObjC++, Java
clang-tidy Static code analyzer C, C++, ObjC
oclint Static code analyzer C, C++, ObjC
uncrustify Formatter C, C++, C#, ObjC, D, Java, Pawn, Vala
cppcheck Static code analyzer C, C++
cpplint Style checker C, C++
include-what-you-use Static code analyzer C, C++

Hook Option Comparison

Hook Options Fix In Place Enable all Checks Set key/value
clang-format -i
clang-tidy --fix-errors [1] -checks=* -warnings-as-errors=* [2]
oclint -enable-global-analysis -enable-clang-static-analyzer -max-priority-3 0 [3] -rc=<key>=<value>
uncrustify --replace --no-backup [4] --set key=value
cppcheck -enable=all
cpplint --verbose=0
include-what-you-use --verbose=3

[1]: -fix will fail if there are compiler errors. -fix-errors will -fix and fix compiler errors if it can, like missing semicolons.

[2]: Be careful with -checks=*. can have self-contradictory rules in newer versions of llvm (9+): modernize wants to use trailing return type but Fuchsia disallows it. Thanks to @rambo.

[3]: The oclint pre-commit hook does the equivalent of -max-priority-3 0 by default, which returns an error code when any check fails. See oclint error codes for more info on partially catching failed checks.

[4]: By definition, if you are using pre-commit, you are using version control. Therefore, it is recommended to avoid needless backup creation by using --no-backup.

Development

See README_dev.md

Additional Resources

clang-format

clang-tidy

oclint

uncrustify

cppcheck

cpplint

include-what-you-use

License

Apache 2.0

pre-commit-hooks's People

Contributors

calinou avatar delgan avatar guihao-liang avatar pocc avatar rambo avatar takishima avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pre-commit-hooks's Issues

Feature request: add support for Include-What-You-Use

Add support for running Include-What-You-Use alongside the other linters in this repository.

The aim of the tool is best described by them on their webpage:

"Include what you use" means this: for every symbol (type, function variable, or macro) that you use in foo.cc, 
either foo.cc or foo.h should #include a .h file that exports the declaration of that symbol. The 
include-what-you-use tool is a program that can be built with the clang libraries in order to analyze 
#includes of source files to find include-what-you-use violations, and suggest fixes for them.

The main goal of include-what-you-use is to remove superfluous #includes. It does this both by figuring out 
what #includes are not actually needed for this file (for both .cc and .h files), and replacing #includes 
with forward-declares when possible.

Since CMake 3.3, IWYU is also natively supported alongside the build (see CMAKE_<LANG>_INCLUDE_WHAT_YOU_USE CMake variable).

The tool also ships with a supporting Python scripts iwyu_tool.py that is able to take advantage of compilation databases (compile_commands.json). For more information see their GitHub page.

clang-format not working in Windows prompt

Hi,
clang-format hook is working fine in git bash on Windows.
However it seems that it doesn't work in 'cmd' prompt on Windows. It fails with the following error:
diff: /dev/fd/63: No such file or directory
It fails whether my C++ file is correctly formatted or not.
I am using this config:

LLVM really includes clang-format and clang-tidy?

Hey! I read in your documentation that installing llvm with brew on Mac should also install clang-format and clang-tidy. This does not work on my machine however. Both clang-format and clang-tidy give me errors suggesting they are not installed when I do pre-commit run -a

Less strict version check

Hello,
Thank you for these hooks. They're great.
I am using clang-format hook.

I'd like to check version of clang-format tool but I think it is too strict.
I'd like to put in my config '--version=6.0'. But some people in my team are using version '6.0.1' while others are using version '6.0.0-1ubuntu2'.

I would be nice to be able to specify a version pattern instead of a strict version. Or use Semantic Versioning if it makes sense.

clang-format not accepting -i

minimal repro

repos:
- repo: https://github.com/pocc/pre-commit-hooks
  sha: master
  hooks:
  - id: clang-format
    args: [--style=Google, -i]
    exclude: \.pb\.(h|cc)$

errors

clang-format.............................................................Failed
- hook id: clang-format
- exit code: 2

diff: missing operand after `/dev/fd/63'
diff: Try `diff --help' for more information.
diff: missing operand after `/dev/fd/63'
diff: Try `diff --help' for more information.

potential root cause

modified utils,

function diff_formatted {
   69   # Quoting $1 interferes with array creation
   70   # shellcheck disable=SC2206
   71   args=($1)
   72   filename="$2"
+  73   echo $filename
   74   if [[ " ${args[*]} " == *" -i "* ]]; then
   75     # Here, diff compares what the file is before and after transform
   76     diff "$filename" <(clang-format "${args[@]}"; cat "$filename")
   77   else
   78     # Otherwise clang-format should send output to stdout, and can be compared
   79     diff "$filename" <(clang-format "${args[@]}")
   80   fi

output:

-i
diff: missing operand after `/dev/fd/63'
diff: Try `diff --help' for more information.
-i
diff: missing operand after `/dev/fd/63'
diff: Try `diff --help' for more information.

The filename is -i, which makes the pipe fail.


question

clang-format supports -i, why you don't want to use it but use diff instead?

Incorrect order of arguments for include-what-you-use?

Maybe I'm just too new to integrating pre-commit into my project and use it incorrectly, but it seems that the arguments for include-what-you-use are passed incorrectly.

The manpage reads
USAGE: include-what-you-use [-Xiwyu --iwyu_opt]... <clang opts> <source file>

but hooks/include_what_you_use.py:25 currently reads
self.run_command([filename] + self.args)

"-p" checking for oclint/clang-tidy always fails

if "-p" is specified alone (so the "-p" in args -check could succeed) clang-tidy complains about missing value.

If it's specified correctly for clang-tidy ("-p=cmake-build-debug") then the check fails and the -D is added which makes clang-tidy not find for example included libraries...

I will submit a PR soonish.

cppcheck hook

Hi,

Thanks for putting this repo together, I just found out about the pre-commit framework after a week of trying to make my own hooks work on my Windows 10 machine and it's much easier to use. This is more a question than a issue.

I'm currently working on a C project and I'm setting on my workflow to launch both clang-format and cppcheck hooks on my files (and ignoring some third party files)

My first question is, if I want to run cppcheck on multiple files, does the following .pre-commit-config.yaml should be able to launch cppcheck on all the .c and .h files under my lm/src directory?

# Exclude vendor autogenerated files
exclude: 'Core'

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.2.0
    hooks:
    -   id: trailing-whitespace
    # Don't let commit in the master branch
    -   id: no-commit-to-branch
        args: ['--branch', 'master']

-   repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.1.1
    hooks:
    # -   id: clang-format
    #     args: [--style=file]
    -   id: cppcheck
        args: ['--quiet', '--enable=all' '--inline-suppr']
        # Run on files with c or h extension on lm directory
        files: 'lm/src/\.(c)$'

The output I'm getting:

Trim Trailing Whitespace.................................................Passed
Don't commit to branch...................................................Passed
cppcheck.............................................(no files to check)Skipped

I've cppcheck v2.3 installed on my Windows 10 machine tho.

Regards

Cppcheck v2.4.1 fails but no output is shown while running pre-commit

Running pre-commit with Cppcheck 2.4.1 on my machine does not provide any output despite the return code not being 0.

Actual:

$ pre-commit run --all-files cppcheck
cppcheck.................................................................Failed
- hook id: cppcheck
- exit code: 1

Expected:

cppcheck.................................................................Failed
- hook id: cppcheck
- exit code: 1

/tmp/temp/src/err.cpp:2:18: style: Unused variable: i [unusedVariable]
int main() { int i; return 10; }
                 ^

include-what-you-use does not fail

include-what-you-use does not fail even if it is supposed to fail. I needed to modify my pre-commit yaml file to include the line entry:

repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.3.5
    hooks:
      - id: uncrustify
      - id: include-what-you-use
        entry: include-what-you-use -Xiwyu --error=1

can I add few more arguments for clang-format and clang-tidy?

I tried to look for answers from early issues but was still confused if it was possible or impossible or on the to-do list.
I think both clang-format and clang-tidy usually need multiple arguments for customization.
Sorry if I missed any critical document already described it.

Is it possible to generate compile_commands.json as part of the hook?

Usually compile_commands.json is created by the build system at the build or generation time. It is never stored in a repo.

Is it possible to add extra option so the database is generated automatically somehow? I can think of this syntax:

repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: python
    hooks:
      - id: clang-tidy
        args: [-p __compdb/compile_commands.json]
        generate_compile_commands: ["mkdir __compdb", "cd __compdb", "cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"]

Is something like this available? Would it make sense?

add_if_missing() does not allow multiple --suppress arguments

Adding a --suppress to the args in the pre-commit-config.yaml like so args: ["--suppress=*:*test*"] will prevent the hook from adding the other default --suppress present in the cppcheck.py :
self.add_if_missing( ["--suppress=unmatchedSuppression", "--suppress=missingIncludeSystem", "--suppress=unusedFunction"] )
This is because the add_if_missing() function will see that a --suppress was already added in the args field so it will not add it again.

Use a clang-format file that isn't at the root of the repo

          > For clang-format, with a `.clang-format` file in the base of your repo:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.3.5
    hooks:
      - id: clang-format
        args: [-i, --style=file]

Thanks for your reply. I will try it.

Originally posted by @sangshuduo in #50 (comment)

Clang-format has a limitation that it only looks in the current director, or above it, when searching for a config file.

I have multiple repositories, A, B, and C.
A and B have source code.
C has common configuration including the clang-format file, which is shared with B and C.

Latest clang-format has support for this: https://stackoverflow.com/a/70859277/11032285

Is there anything that I should do to use that?

clang-tidy fails due to warnings in non-user code

If I include a standard header e.g. stdio.h, clang-tidy will analyse it and fail because the header's content doesn't comply with the checks:

2816 warnings generated.
Suppressed 2816 warnings (2816 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

In the context of pre-commit, this is a problem because it causes the process to exit with code 1. Therefore, the check fails even though these warnings are being "suppressed". clang-tidy clearly knows these warnings are not from user code, yet I cannot find a way to make it stop exiting with code 1 (--quiet doesn't help). I'm a novice with clang-tidy, so I may have misconfigured something.

With this in mind, how is it even practical to use clang-tidy at all with pre-commit? How do you use it?

Running against files with non UTF-8 characters results in UnicodeErrors

Traceback (most recent call last):
  File "/home/dave/.cache/pre-commit/repov7j0xgwa/py_env-python3.8/bin/uncrustify-hook", line 8, in <module>
    sys.exit(main())
  File "/home/dave/.cache/pre-commit/repov7j0xgwa/py_env-python3.8/lib/python3.8/site-packages/hooks/uncrustify.py", line 53, in main
    cmd.run()
  File "/home/dave/.cache/pre-commit/repov7j0xgwa/py_env-python3.8/lib/python3.8/site-packages/hooks/uncrustify.py", line 45, in run
    self.compare_to_formatted(filename)
  File "/home/dave/.cache/pre-commit/repov7j0xgwa/py_env-python3.8/lib/python3.8/site-packages/hooks/utils.py", line 164, in compare_to_formatted
    actual = self.get_filelines(filename)
  File "/home/dave/.cache/pre-commit/repov7j0xgwa/py_env-python3.8/lib/python3.8/site-packages/hooks/utils.py", line 203, in get_filelines
    return str(filetext, encoding="utf-8").split("\n")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 in position 631: invalid start byte

Perhaps an additional parameter in the yaml file? It can default to UTF-8, but allow the user to configure it if they want something else?

Have clang-format change files

Thanks for this !

For Python pre-commit is able to apply the proposed changes to the files, so that one has to just review the changes with git. Can the same be done here?

Example hook config for vala

Pre-commit does not find stagged vala file.
As I saw you comment here, it seems that this hook does not work with vala

# D, vala currently aren't valid file types. See https://github.com/pre-commit/identify/issues/258

I just want to get a comfirm before going in the rabbit hole, is this possible?

clang-format stops working when using --version

With the default test repo (pre-commit-hooks/tests/test_repo) and the following config...

fail_fast: false
repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.3.5
    hooks:
      - id: clang-format
        args: [--version=10.0.0, --style=Google]

... the following happens (incorrectly, it should detect the incorrect formatting):

$ pre-commit run -a
clang-format.............................................................Passed

But when I remove --version=10.0.0, it's working:

$ pre-commit run -a
clang-format.............................................................Failed
- hook id: clang-format
- exit code: 1

err.cpp
====================
--- original

+++ formatted

@@ -1,2 +1,5 @@

 #include <string>
-int main(){int i;return;}
+int main() {
+  int i;
+  return;
+}
err.c
====================
--- original

+++ formatted

@@ -1,2 +1,5 @@

 #include <stdio.h>
-int main(){int i;return;}
+int main() {
+  int i;
+  return;
+}

Class ClangTidyCmd disregards its `args` parameter

I noticed this issue with ClangTidyCmd but it it is an issue for all the other similar concrete classes (CppcheckCmd, CpplintCmd, IncludeWhatYouUseCmd, etc.).

I am working on a cross-platform C++ repo that has windows/ and linux/ subfolders for implementations on a specific OS. I'm setting up linting. Clang-tidy, as expected, can only process the code for the current system (Linux / Windows). e.g. if I am on Linux and run your hooks with the command pre-commit run --all-files clang-tidy, it will try to parse the Windows files and error out.

Because pre-commit-config.yaml does not take variables, I created a shim script that filters out any files from the wrong folder. For example, if I am on Linux and pre-commit passes some file named foo/windows/bar.cpp in argv, the shim will create a new list without that file and call your hook.

.pre-commit-config.yaml:

repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.3.5
    hooks:
      - id: clang-tidy
        entry: scripts/pocc-shim.py

scripts/pocc-shim.py:

def main() -> int:
    """Filter out filenames from other system implementations and call pocc's clang-tidy hook with the modified args."""

    if sys.platform == "win32":
        exclude = "linux"
    elif sys.platform == "linux":
        exclude = "windows"
    else:
        raise NotImplementedError(f"Not implemented for system: {sys.platform}")

    filtered_args = shim_utils.filter_args(exclude, sys.argv)
    return hooks.clang_tidy.main(filtered_args)

The issue is that this doesn't work. Clang-tidy is still failing on files shouldn't have been passed to it.

I had a look at utils.py and saw that Command.get_added_files is reading directly from sys.argv instead of the args variable passed in.

My current workaround is to just set sys.argv.
scripts/pocc-shim.py:

filtered_args = shim_utils.filter_args(exclude, sys.argv)
sys.argv = filtered_args  # set sys.argv as workaround
return hooks.clang_tidy.main(filtered_args)

After this, the hook passes on both systems, properly ignoring files from the excluded folders.

I find this workaround distasteful, but it works fine and is acceptable for my purposes.

However, the underlying issue should still be addressed.

Repro

You can see my code here akfreed/CppSocketsXPlatform@df8ac58. At the moment it is easier to reproduce on Linux. You will need clang-tidy version 13 (I installed with brew).

OS: Ubuntu 20
Toolchain: (All Ubuntu 20 apt default versions except clang-tidy)

git clone https://github.com/akfreed/CppSocketsXPlatform.git 
cd CppSocketsXPlatform
git checkout df8ac584207130e305de562e01e154407857e2ea
git submodule update --init --recursive
mkdir build && cd build
cmake ..
cd ..
python3 -m venv .venv
. .venv/bin/activate
pip install -U pip
pip install pre-commit
pre-commit run --all-files clang-tidy

Expected result

(.venv) freed@ubuntu20:~/cpp/repro$ pre-commit run --all-files clang-tidy
[INFO] Installing environment for https://github.com/pocc/pre-commit-hooks.                                     [INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
clang-tidy...............................................................Passed

Actual result

it fails on a file under the windows folder

(.venv) freed@ubuntu20:~/cpp/repro$ pre-commit run --all-files clang-tidy
clang-tidy...............................................................Failed
- hook id: clang-tidy                                                                                           - exit code: 1

/home/freed/cpp/repro/StrapperNet/lib/windows/SocketHandle.cpp:25:1: error: constructor does not initialize thes
e fields: m_socketId [cppcoreguidelines-pro-type-member-init,hicpp-member-init,-warnings-as-errors]
SocketHandle::SocketHandle() = default;                                                                         ^
...
...lots and lots of errors...
...

can `--version` enforce using a clang-format version if more than one are installed?

Thanks for the great hooks!

My interpretation of the documentation was that --version=X would try to enforce using version X of a linter. However, it seems that it only validates the correct version is used.
E.g. in one of my ubuntu machines, the clang-format binary is at version 10, but version 11 is also installed (as clang-format-11).

Would it make sense that --version=11 would try to use the latter? Otherwise, could we have a knob exposed for the binary that the hook will use?

Uncrustify hook doesn't allow you to specify uncrustify commandline arguments.

I'm trying to use the uncrustify hook, but if you try to specify a language or configuration file, the parser seems to think they are file names instead of arguments?

Config file:

repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.1.1
    hooks:
      - id: uncrustify
        args: ["-l CPP", "-c build/uncrustify.cfg", "--replace" ]

Example error call stack:

[INFO] Stashing unstaged files to C:\Users\test\.cache\pre-commit\patch1629754966-43936.
uncrustify...............................................................Failed
- hook id: uncrustify
- duration: 0.31s
- exit code: 1

Traceback (most recent call last):
  File "c:\users\test\scoop\apps\python\3.9.6\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\test\scoop\apps\python\3.9.6\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\test\.cache\pre-commit\repo3sfmc84z\py_env-default\Scripts\uncrustify-hook.EXE\__main__.py", line 7, in <module>
  File "C:\Users\test\.cache\pre-commit\repo3sfmc84z\py_env-default\lib\site-packages\hooks\uncrustify.py", line 55, in main
    cmd.run()
  File "C:\Users\test\.cache\pre-commit\repo3sfmc84z\py_env-default\lib\site-packages\hooks\uncrustify.py", line 47, in run
    self.compare_to_formatted(filename)
  File "C:\Users\test\.cache\pre-commit\repo3sfmc84z\py_env-default\lib\site-packages\hooks\utils.py", line 164, in compare_to_formatted
    actual = self.get_filelines(filename)
  File "C:\Users\test\.cache\pre-commit\repo3sfmc84z\py_env-default\lib\site-packages\hooks\utils.py", line 201, in get_filelines
    with open(filename, "rb") as f:
FileNotFoundError: [Errno 2] No such file or directory: '-l CPP'

Why use diff instead of exit status for pass/fail?

On macOS if I pass --check=* to clang-tidy, it flags a macro expanded from a system header. If I add the appropriate clang-tidy directive to ignore the error on that line, the pre-commit hook still fails:

clang-tidy...........................................................................Failed
hookid: clang-tidy

1080 warnings generated.
Suppressed 1090 warnings (1080 in non-user code, 10 NOLINT).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

oclint multiple execution and inability to see the output

Hi!

I am trying to configure the pre-commit hook with oclint.

What I am noticing is that while executing the commit the program is executed but...

  • the program seems to run for each file that is changed
  • there's no clear output of what to fix

as an example this is the output that I get from a test application:

oclint...................................................................Failed
- hook id: oclint
- exit code: 5

oclint: error: violations exceed threshold
P1=0[0] P2=0[0] P3=3[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=0[0] P3=2[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=1[0] P3=1[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=0[0] P3=3[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=0[0] P3=4[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=0[0] P3=1[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=2[0] P3=3[0] 

oclint: error: violations exceed threshold
P1=0[0] P2=0[0] P3=1[0]

If I try to attach the html output in the configuration yaml, then the file is always rewritten with the last run. If I execute oclint from command line, then, I have an html file that groups all the outputs from every file.

clang-tidy: for the -p option: may not occur within a group!

Hi, I am trying to use the clang-tidy hook.
my .pre-commit-config.yaml looks something like:
`repos:

Notice the args. I specify the path to the database.

When trying to run, I get:
clang-tidy: for the -p option: may not occur within a group! error: clang-tidy: Unknown command line argument '-p build/meson'. Try: 'clang-tidy --help' clang-tidy: Did you mean '-p'?

Thank you for your help

Migrate to Python3 instead of Bash?

@guihao-liang @sparfenyuk @TheButlah @zbeekman @bsergean You guys have interacted with this repo and I'd like your input. Issues have been created in part due to how bash parses strings or interacts with arrays/hash maps (#5, #9, #10), or how it's not even the same across platforms (#4 - thanks to zbeekman for a likely fix).

Python is required to install pre-commit and so everyone using pre-commit already has it on their system. Python has more predictable behavior, which is what I'm aiming for here in contrast to bash (e.g. ${args[*]} vs ${args[@]}). It's also a well-known glue language for C/C++, so it would fit well here.

Thoughts?

file regex not read from the configuration file

At line 28 of hooks/utils.py , the comment says that this would capture the target files from the configuration file, but it seems to me that in reality the only file regex that it uses are the ones that are hardcoded, right after those lines.

Is that an actual error and/or are there plans to fix that?

def set_file_regex(self):
        """Get the file regex for a command's target files from the .pre-commit-hooks.yaml."""

file not found [clang-diagnostic-error] #include "lib1.h" ^~~~~~~~

my pre-commit file look like:

fail_fast: false
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0  # Use the ref you want to point at
    hooks:
    -   id: trailing-whitespace
    -   id: check-added-large-files
-   repo: https://github.com/pocc/pre-commit-hooks
    rev: master
    hooks:
      - id: clang-format
        args: [-i]
      - id: clang-tidy
      # - id: oclint
      # - id: uncrustify
      # - id: cppcheck
      # - id: cpplint

and it's a cmake c++ projects and I added set(CMAKE_EXPORT_COMPILE_COMMANDS ON) on my cmakelist.txt
and cmake generate file namedcompile_commands.json and it`s contain the file c++ src file path.

{
  "directory": "/Users/chendongsheng/github/cmake_test/build",
  "command": "/usr/bin/clang++ -I/Users/chendongsheng/github/cmake_test/lib1/. -I/Users/chendongsheng/github/cmake_test/lib2/. -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -o lib1/CMakeFiles/lib1.dir/aaa.cpp.o -c /Users/chendongsheng/github/cmake_test/lib1/aaa.cpp",
  "file": "/Users/chendongsheng/github/cmake_test/lib1/aaa.cpp"
},

but when i try to run pre-commit run --all-files

I got error like:

[WARNING] The 'rev' field of repo 'https://github.com/pocc/pre-commit-hooks' appears to be a mutable reference (moving tag / branch).  Mutable references are never updated after first install and are not supported.  See https://pre-commit.com/#using-the-latest-version-for-a-repository for more details.  Hint: `pre-commit autoupdate` often fixes this.
trim trailing whitespace.................................................Passed
check for added large files..............................................Passed
clang-format.............................................................Passed
clang-tidy...............................................................Failed
- hook id: clang-tidy
- exit code: 1

/Users/chendongsheng/github/cmake_test/app/main.cpp:1:10: error: 'lib1.h' file not found [clang-diagnostic-error]
#include "lib1.h"
         ^~~~~~~~
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "lib1/aaa.cpp"
No compilation database found in /Users/chendongsheng/github/cmake_test/lib1 or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "app/main.cpp"
No compilation database found in /Users/chendongsheng/github/cmake_test/app or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 error generated.
Error while processing /Users/chendongsheng/github/cmake_test/app/main.cpp.
Found compiler error(s).

Resolve Tooling and support multiple version of clang-tidy

Currently, the hooks require tooling to be available on the machines where the hooks are running. Would the project be open to supporting specifying which version of clang-tidy to download and download the appropriate version on the machine as part of pre-commit so that the user doesn't have to worry about installing the tooling?

The upstream has clang-tidy releases multiple versions of clang-tidy.
and the pre-commit for clang downloads the specific version corresponding to os based on version arg provided for the hook.

Happy to look into a patch along these lines.

Better document oclint return codes

If you specify the -max-priority-3 0 as an option for the file int main() { int i; return 10; }, oclint will return 5 instead of 0. My understanding of oclint return codes was faulty in that there are various levels of errors, some of which are suppressed by default vis-a-vis the return code.

More information about this issue can be found at oclint/oclint#538

Additional info can be found about this oclint flag is at https://docs.oclint.org/en/stable/manual/oclint.html#exit-status-options

unittest failure for clang-tidy

_______________________________________________________________________ TestCLinters.test_clang_tidy_err ________________________________________________________________________

self = <tests.hooks_test.TestCLinters object at 0x110d08128>

        def test_clang_tidy_err(self):
            clang_tidy_error = r"""{0}:1:28: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,-warnings-as-errors]
    int main() {{ int i; return 10; }}
                               ^
    """  # noqa: E501
            self.run_clang_tidy(
                filelist=self.errfiles,
                expected_output=clang_tidy_error,
>               expected_retcode=1,
            )

tests/hooks_test.py:127: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.hooks_test.TestCLinters object at 0x110d08128>
filelist = ['/Users/guihaoliang/Work/playground/github/pre-commit-hooks/tests/files/err.c', '/Users/guihaoliang/Work/playground/github/pre-commit-hooks/tests/files/err.cpp']
expected_output = '{0}:1:28: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,-warnings-as-errors]\nint main() {{ int i; return 10; }}\n                           ^\n'
expected_retcode = 1, version = ''

    def run_clang_tidy(self, filelist, expected_output, expected_retcode, version=""):
        """Test that clang tidy returns correct retcode & output for files."""
        cmds = [
            "./hooks/clang-tidy",
            "-quiet",
            "-checks=*",
            "-warnings-as-errors=*",
        ]
        if version:
            cmds += ["--version=" + version]
        for filename in filelist:
            if version:  # Version docstring doesn't contain a {0}
                expected = expected_output
            else:
                expected = expected_output.format(filename)
            # In case num warnings changes due to more checks
            actual, retcode = self.get_all_output(cmds, filename)
            actual = re.sub(r"^\d+", "2", actual)
            # Expecting error text with a err return code
>           assert actual == expected
E           AssertionError: assert '/Users/guiha...          ^\n' == '/Users/guiha...          ^\n'
E             - /Users/guihaoliang/Work/playground/github/pre-commit-hooks/tests/files/err.cpp:1:5: error: use a trailing return type for this function [modernize-use-trailing-return-type,-warnings-as-errors]
E             - int main() { int i; return 10; }
E             - ~~~ ^
E             - auto       -> int
E               /Users/guihaoliang/Work/playground/github/pre-commit-hooks/tests/files/err.cpp:1:28: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,-warnings-as-errors]
E               int main() { int i; return 10; }
E                                          ^

tests/hooks_test.py:166: AssertionError
===========================================

clang format failed

pre-commit run
clang-format.............................................................Failed
- hook id: clang-format
- exit code: 1

firmware/src/main.cpp
====================
--- original
+++ formatted
@@ -33,7 +33,7 @@
 // Section: Main Entry Point
 // *****************************************************************************
 // *****************************************************************************
-int x= 0;
+int x = 0;
 int main(void) {

which clang-format
/home/USER/.local/bin/clang-format

Ubuntu 22 LTS
clang-format LLVM installed locally

Any way to find out why it failed?

thanks

clang-tidy ignores provided `-p` option

I am trying to set the directory where compile_commands.json file exists by using -p argument. Clang-tidy hook doesn't use it much. It causes errors while the tool looks for external libraries that are used in the project.

fail_fast: false
repos:
  - repo: https://github.com/pocc/pre-commit-hooks
    rev: master
    hooks:
      - id: clang-format
        types: [c++]
      - id: clang-tidy
        args: [-p=/home/user/projects/myproject/build]

clang-tidy file exclude pattern ignored

Hi,

I would like to run all of the hooks only on specific directories. To achieve this I'm using file exclude pattern. The exclude works for the clang-format but not for the clang-tidy (for example it reports errors in Utilities directory with manufacturer files). Basically clang-tidy takes all files.

How I can make the exclude pattern work for clang-tidy also? I saw files: .*\.c option but I would have to repeat the excludes in - id: clang-tidyhook

PS. I noticed cpplint also runs on all the files and ignores file exclude pattern

Here is my config file:

exclude: |
  (?x)^(
      .vscode/.*|
      Core/.*|
      Drivers/.*|
      LoRaWAN/.*|
      Middlewares/Third_Party/.*|
      Utilities/.*|
      config/.*|
      ^.*\.(svd|ld)|
      .mxproject
  )$

repos:
  - repo: local
    hooks:
      - id: compiledb
        name: compiledb
        entry: compiledb
        language: system
        args: [--overwrite, make, -n, -B]
        always_run: true
        require_serial: true
        pass_filenames: false

  - repo: https://github.com/pre-commit/mirrors-clang-format
    rev: v14.0.6
    hooks:
      - id: clang-format

  - repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.3.5
    hooks:
      - id: cpplint
      - id: clang-tidy
        args: [-checks=clang-diagnostic-return-type]

clang-format -i should fix all files, not one at a time.

Issue's target is master. To reproduce, create a repo with two err files and run clang-format-hook over it with -i.

Current

Current behavior is to immediately fail if there's one file that's failing.

Expected

Expected (and more useful) behavior is to fix all files and then fail.

Configurable `uncrustify` executable path for the uncrustify hook

I have seen in the hook's code that uncrustify is hardcoded as a command. It would be really useful to specify some custom path for the executable, e.g. /home/skelly37/.local/bin/uncrustify, so the end-user can have multiple uncrustify installations or so they do not have to mess with the system's PATH

If I can already do something like this, I would appreciate showing me how to do it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.