Merge bitcoin/bitcoin#31435: lint: Move assertion linter into lint runner

e8f0e6efaf lint: output-only - Avoid repeated arrows, trim (Hodlinator)
fa9aacf614 lint: Move assertion linter into lint runner (MarcoFalke)

Pull request description:

  On failure, this makes the output more consistent with the other linters. Each failure will be marked with an '⚠️ ' emoji and explanation, making it easier to spot.

  Also, add --line-number to the filesystem linter.

  Also, add newlines after each failing check, to visually separate different failures from each other.

  Can be reviewed with:
  `--color-moved=dimmed-zebra --color-moved-ws=ignore-all-space`

ACKs for top commit:
  davidgumberg:
    crACK e8f0e6efaf
  hodlinator:
    re-ACK e8f0e6efaf
  TheCharlatan:
    ACK e8f0e6efaf

Tree-SHA512: 9896ff882af9d673ec3e6d2718f877b2fdc8514faba50942fcebacb9de95b1f5b4a5db595e1338fa7f505d06df2df304897350cc55c558c7a85232800e5fd804
This commit is contained in:
merge-script 2025-01-06 13:35:40 +00:00
commit 6475849c40
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1
2 changed files with 84 additions and 72 deletions

View file

@ -1,54 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2018-2022 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Check for assertions with obvious side effects.
import sys
import subprocess
def git_grep(params: [], error_msg: ""):
try:
output = subprocess.check_output(["git", "grep", *params], text=True, encoding="utf8")
print(error_msg)
print(output)
return 1
except subprocess.CalledProcessError as ex1:
if ex1.returncode > 1:
raise ex1
return 0
def main():
# Aborting the whole process is undesirable for RPC code. So nonfatal
# checks should be used over assert. See: src/util/check.h
# src/rpc/server.cpp is excluded from this check since it's mostly meta-code.
exit_code = git_grep([
"--line-number",
"--extended-regexp",
r"\<(A|a)ss(ume|ert)\(",
"--",
"src/rpc/",
"src/wallet/rpc*",
":(exclude)src/rpc/server.cpp",
], "CHECK_NONFATAL(condition) or NONFATAL_UNREACHABLE should be used instead of assert for RPC code.")
# The `BOOST_ASSERT` macro requires to `#include boost/assert.hpp`,
# which is an unnecessary Boost dependency.
exit_code |= git_grep([
"--line-number",
"--extended-regexp",
r"BOOST_ASSERT\(",
"--",
"*.cpp",
"*.h",
], "BOOST_ASSERT must be replaced with Assert, BOOST_REQUIRE, or BOOST_CHECK.")
sys.exit(exit_code)
if __name__ == "__main__":
main()

View file

@ -48,6 +48,16 @@ fn get_linter_list() -> Vec<&'static Linter> {
name: "std_filesystem", name: "std_filesystem",
lint_fn: lint_std_filesystem lint_fn: lint_std_filesystem
}, },
&Linter {
description: "Check that fatal assertions are not used in RPC code",
name: "rpc_assert",
lint_fn: lint_rpc_assert
},
&Linter {
description: "Check that boost assertions are not used",
name: "boost_assert",
lint_fn: lint_boost_assert
},
&Linter { &Linter {
description: "Check that release note snippets are in the right folder", description: "Check that release note snippets are in the right folder",
name: "doc_release_note_snippets", name: "doc_release_note_snippets",
@ -273,6 +283,7 @@ fn lint_std_filesystem() -> LintResult {
let found = git() let found = git()
.args([ .args([
"grep", "grep",
"--line-number",
"std::filesystem", "std::filesystem",
"--", "--",
"./src/", "./src/",
@ -283,10 +294,66 @@ fn lint_std_filesystem() -> LintResult {
.success(); .success();
if found { if found {
Err(r#" Err(r#"
^^^
Direct use of std::filesystem may be dangerous and buggy. Please include <util/fs.h> and use the Direct use of std::filesystem may be dangerous and buggy. Please include <util/fs.h> and use the
fs:: namespace, which has unsafe filesystem functions marked as deleted. fs:: namespace, which has unsafe filesystem functions marked as deleted.
"# "#
.trim()
.to_string())
} else {
Ok(())
}
}
fn lint_rpc_assert() -> LintResult {
let found = git()
.args([
"grep",
"--line-number",
"--extended-regexp",
r"\<(A|a)ss(ume|ert)\(",
"--",
"src/rpc/",
"src/wallet/rpc*",
":(exclude)src/rpc/server.cpp",
// src/rpc/server.cpp is excluded from this check since it's mostly meta-code.
])
.status()
.expect("command error")
.success();
if found {
Err(r#"
CHECK_NONFATAL(condition) or NONFATAL_UNREACHABLE should be used instead of assert for RPC code.
Aborting the whole process is undesirable for RPC code. So nonfatal
checks should be used over assert. See: src/util/check.h
"#
.trim()
.to_string())
} else {
Ok(())
}
}
fn lint_boost_assert() -> LintResult {
let found = git()
.args([
"grep",
"--line-number",
"--extended-regexp",
r"BOOST_ASSERT\(",
"--",
"*.cpp",
"*.h",
])
.status()
.expect("command error")
.success();
if found {
Err(r#"
BOOST_ASSERT must be replaced with Assert, BOOST_REQUIRE, or BOOST_CHECK to avoid an unnecessary
include of the boost/assert.hpp dependency.
"#
.trim()
.to_string()) .to_string())
} else { } else {
Ok(()) Ok(())
@ -303,17 +370,15 @@ fn lint_doc_release_note_snippets() -> LintResult {
if non_release_notes.is_empty() { if non_release_notes.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(format!( println!("{non_release_notes}");
r#" Err(r#"
{}
^^^
Release note snippets and other docs must be put into the doc/ folder directly. Release note snippets and other docs must be put into the doc/ folder directly.
The doc/release-notes/ folder is for archived release notes of previous releases only. Snippets are The doc/release-notes/ folder is for archived release notes of previous releases only. Snippets are
expected to follow the naming "/doc/release-notes-<PR number>.md". expected to follow the naming "/doc/release-notes-<PR number>.md".
"#, "#
non_release_notes .trim()
)) .to_string())
} }
} }
@ -356,7 +421,6 @@ fn lint_trailing_whitespace() -> LintResult {
.success(); .success();
if trailing_space { if trailing_space {
Err(r#" Err(r#"
^^^
Trailing whitespace (including Windows line endings [CR LF]) is problematic, because git may warn Trailing whitespace (including Windows line endings [CR LF]) is problematic, because git may warn
about it, or editors may remove it by default, forcing developers in the future to either undo the about it, or editors may remove it by default, forcing developers in the future to either undo the
changes manually or spend time on review. changes manually or spend time on review.
@ -366,6 +430,7 @@ Thus, it is best to remove the trailing space now.
Please add any false positives, such as subtrees, Windows-related files, patch files, or externally Please add any false positives, such as subtrees, Windows-related files, patch files, or externally
sourced files to the exclude list. sourced files to the exclude list.
"# "#
.trim()
.to_string()) .to_string())
} else { } else {
Ok(()) Ok(())
@ -382,7 +447,6 @@ fn lint_tabs_whitespace() -> LintResult {
.success(); .success();
if tabs { if tabs {
Err(r#" Err(r#"
^^^
Use of tabs in this codebase is problematic, because existing code uses spaces and tabs will cause Use of tabs in this codebase is problematic, because existing code uses spaces and tabs will cause
display issues and conflict with editor settings. display issues and conflict with editor settings.
@ -390,6 +454,7 @@ Please remove the tabs.
Please add any false positives, such as subtrees, or externally sourced files to the exclude list. Please add any false positives, such as subtrees, or externally sourced files to the exclude list.
"# "#
.trim()
.to_string()) .to_string())
} else { } else {
Ok(()) Ok(())
@ -464,7 +529,6 @@ fn lint_includes_build_config() -> LintResult {
if missing { if missing {
return Err(format!( return Err(format!(
r#" r#"
^^^
One or more files use a symbol declared in the bitcoin-build-config.h header. However, they are not One or more files use a symbol declared in the bitcoin-build-config.h header. However, they are not
including the header. This is problematic, because the header may or may not be indirectly including the header. This is problematic, because the header may or may not be indirectly
included. If the indirect include were to be intentionally or accidentally removed, the build could included. If the indirect include were to be intentionally or accidentally removed, the build could
@ -480,12 +544,13 @@ include again.
#include <bitcoin-build-config.h> // IWYU pragma: keep #include <bitcoin-build-config.h> // IWYU pragma: keep
"#, "#,
defines_regex defines_regex
)); )
.trim()
.to_string());
} }
let redundant = print_affected_files(false); let redundant = print_affected_files(false);
if redundant { if redundant {
return Err(r#" return Err(r#"
^^^
None of the files use a symbol declared in the bitcoin-build-config.h header. However, they are including None of the files use a symbol declared in the bitcoin-build-config.h header. However, they are including
the header. Consider removing the unused include. the header. Consider removing the unused include.
"# "#
@ -538,7 +603,9 @@ Markdown link errors found:
{} {}
"#, "#,
stderr stderr
)) )
.trim()
.to_string())
} }
Err(e) if e.kind() == ErrorKind::NotFound => { Err(e) if e.kind() == ErrorKind::NotFound => {
println!("`mlc` was not found in $PATH, skipping markdown lint check."); println!("`mlc` was not found in $PATH, skipping markdown lint check.");
@ -590,10 +657,9 @@ fn main() -> ExitCode {
env::set_current_dir(&git_root).unwrap(); env::set_current_dir(&git_root).unwrap();
if let Err(err) = (linter.lint_fn)() { if let Err(err) = (linter.lint_fn)() {
println!( println!(
"{err}\n^---- ⚠️ Failure generated from lint check '{}'!", "^^^\n{err}\n^---- ⚠️ Failure generated from lint check '{}' ({})!\n\n",
linter.name linter.name, linter.description,
); );
println!("{}", linter.description);
test_failed = true; test_failed = true;
} }
} }