Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pre-commit: Add clang-tidy hook #2982

Closed
wants to merge 9 commits into from

Conversation

Holzhaus
Copy link
Member

@Holzhaus Holzhaus commented Aug 1, 2020

Follow up to #2981 and replaces #2975. Unsure if we want this, but I think it makes sense.

This merges the clang-format and line-length hooks into a single one.
Semantically, this makes way more sense. Also, this prevent multiple
attempted commit that are rejected by pre-commit (pre-commit might skip
the line-length hook if old clang-format hook already failed).

Also, this removes any dependency on git-clang-format and implements the
whole mechanism itself. It retrieves all added lines from the unified diff
instead and is now capable of taking PRE_COMMIT_FROM_REF into account.

By moving the git-related code into a separate githelper library, it's
way easier to write additional python wrappers for new hooks, e.g. for
clang-tidy.
@Holzhaus Holzhaus marked this pull request as draft August 1, 2020 10:56
@Holzhaus Holzhaus mentioned this pull request Aug 1, 2020
Comment on lines +1 to +7
---
Checks: '-*,modernize-use-nullptr,modernize-use-auto'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do this! This will disable all checks for a standard run of clang-tidy across the project. The scope of checks for the hook is intentionally very narrow to be uncontroversial, but this shouldn't be the default for a normal run.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can still reenable the checks when running on the command line. We should strive to keep manual runs and the pre-commit invocations consistent. If we really add clang-tidy support, we should just add all desired checks to this config file IMHO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, please not. Then it starts warning about all sorts of things that it can't automatically fix in the hook. Just don't.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main problem is that clang-tidy doesn't seem to completely restrict itself to the lines you limited it too, so it can quickly become very verbose.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should just add all desired checks to this config file IMHO.

Then it starts warning about all sorts of things that it can't automatically fix in the hook. Just don't.

The word desired is key here 😄 Support for auto-fixing is not a prerequite for using it in pre-commit though. We already have other hooks that may fail without auto-fix (certain eslint rules, qsscheck, etc.). The point is that it prevents us from committing questionable code.

Also, if we add a clang-tidy config file to the repo it also enables IDE/editors to pick it up and already warn us while writing code with the configuration tailored to Mixxx.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, currently my IDE is warning me about the clang tidy default checks, with this config this would all go away. If you really want a full-blown config then don't start with -*.
But maybe we can start with a minimal one, because I am pretty sure some checks will be controversial and thus unneccessarily delay the merge.

Comment on lines +1 to +7
---
Checks: '-*,modernize-use-nullptr,modernize-use-auto'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, currently my IDE is warning me about the clang tidy default checks, with this config this would all go away. If you really want a full-blown config then don't start with -*.
But maybe we can start with a minimal one, because I am pretty sure some checks will be controversial and thus unneccessarily delay the merge.

Comment on lines +49 to +57
parser = argparse.ArgumentParser()
parser.add_argument("--from-ref", help="compare against git reference")
parser.add_argument("files", nargs="*", help="only check these files")
args = parser.parse_args(argv)

if not args.from_ref:
args.from_ref = os.getenv("PRE_COMMIT_FROM_REF") or os.getenv(
"PRE_COMMIT_SOURCE"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see repetition ;P

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The symlink to the compile_commands.json reveals a conceptual issue.
The pre-commit hook checks the source code independent from a build. While the test targets are checking the single build configurations config.

I think we need a different approach here. clang-tidy should become a part of the build system and should be treated the same as other compiler warnings.
Clang-tidy is then a special "warning level"

This way we have a Clang-tidy check for all our build targets.

A CI check can than verify that a build does not produce new CI warnings. Jenkins can do this, so I guess Travis and Appveyor are able to do this as well.

Interesting:
https://github.com/zemasoft/clangformat-cmake

@@ -319,6 +319,13 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()

# Export compile-commands.json and symlink it into the source directory (needed
# for clang-tidy pre-commit hook)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be remain a user option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean with a "user option"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it only creates a json-file in the cmake build directory, I don't see a need to ever disable that.

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
file(CREATE_LINK
${CMAKE_BINARY_DIR}/compile_commands.json
${CMAKE_SOURCE_DIR}/compile_commands.json SYMBOLIC)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clutters the working directory. I think we should look out for an alternative solution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I struggled with this for hours, believe me. Supposedly adding the -p argument to clang-tidy allows you to specify a directory where the json resides, but it did not work for me at all. And even if it worked - how do you know the name of the cmake build directory? It can be different for everyone.
Furthermore, this also enables you to run clang-tidy manually without any setup.
And it's not like we have a super-tidy working directory now ^^

@@ -0,0 +1,137 @@
#!/usr/bin/env python3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this change obsolete now?

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file need to integrate the changes from clang_format.py form master.

@Holzhaus
Copy link
Member Author

I found out that this is uneeded with CMake. When running CMake you can easily do this:

$ cmake -DCMAKE_CXX_CLANG_TIDY=clang-tidy ..

Or even specify arguments:

$ cmake -DCMAKE_CXX_CLANG_TIDY='clang-tidy -checks=-*,readability-*'

Closing this.

@Holzhaus Holzhaus closed this Aug 15, 2020
@daschuer
Copy link
Member

Can you describe this in the wiki?

@xeruf
Copy link
Contributor

xeruf commented Aug 17, 2020

@Holzhaus but that way doesn't allow us to automatically update only changed lines?

@xeruf
Copy link
Contributor

xeruf commented Aug 19, 2020

@Holzhaus please reopen. The whole point why I started this is to allow these things to be automatically fixed, which your solution doesn't do.

Btw, we definitely also want this check ;) http://clang.llvm.org/extra/clang-tidy/checks/readability-braces-around-statements.html

@Holzhaus
Copy link
Member Author

The problem is that his doesn't work properly because it relies on the compile-commands.json. We have not way to check/ensure that this file is in sync with the source code. We'd also need to install all CMake dependencies into the pre-commit build vm on Travis.

I don't know how to solve this. I'd be in favor of adding a clang tidy config file to the repository and then relying on your editor to lint while typing, so that you can fix things manually. Using nullptr instead of NULL is not exactly rocket science, and since we don't want to do mass reformattings, replacing it automatically would be nice-to-have but is not imperative.

@xeruf
Copy link
Contributor

xeruf commented Aug 19, 2020

We'd also need to install all CMake dependencies into the pre-commit build vm on Travis.

You can disable clang-tidy on CI - it was intended as a developer aid.

I'd be in favor of adding a clang tidy config file to the repository and then relying on your editor to lint while typing

Sure, I am already doing that. But as stated above, that file should be much more generous with its checks and not start with -*.

The problem is that his doesn't work properly because it relies on the compile-commands.json.

Maybe we can add this to pre-commit in a way that it is disabled by default and can be enabled with an environment variable?

Otherwise I have to keep this local. This was an option for me from the very beginning, though it is not convenient.

@xeruf
Copy link
Contributor

xeruf commented Aug 19, 2020

Using nullptr instead of NULL is not exactly rocket science, and since we don't want to do mass reformattings, replacing it automatically would be nice-to-have but is not imperative.

Adding braces, replacing NULL with nullptr... all mundane things that we have tools for. I don't want to keep wasting time on such things if we can easily automate them.

Or as Uwe puts it: I just don't want to think about it!

Every time I go from review to IDE to fix such a thing is an unnecessary context switch.

@xeruf
Copy link
Contributor

xeruf commented Aug 21, 2020

So, we can't create a pre-commit hook that is disabled by default, but we can implement the hook in such a way that it only runs when a specific environment variable is set. Thus we shift the responsibility of making the compilation database available to the user.

And if we get it working with clang-tidy, we could even use the environment variable not only as a flag, but it could contain the location of the compilation database, then we don't have to necessarily symlink it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants