2023-01-25 17:35:53 +00:00
|
|
|
#!/usr/bin/env python3
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-05-31 19:03:38 +01:00
|
|
|
import argparse
|
2022-06-24 12:55:42 +01:00
|
|
|
import fnmatch
|
2021-05-18 14:31:49 +01:00
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import shutil
|
2022-05-31 12:24:29 +01:00
|
|
|
import subprocess
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-05-30 17:05:21 +01:00
|
|
|
# ---------- actual list of lints to apply (or disapply) ----------
|
2021-05-18 14:31:49 +01:00
|
|
|
|
|
|
|
WANT_LINTS = """
|
2022-06-23 19:14:11 +01:00
|
|
|
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
|
|
|
|
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]
|
2021-05-18 14:31:49 +01:00
|
|
|
#![deny(missing_docs)]
|
2021-05-27 19:32:29 +01:00
|
|
|
#![warn(noop_method_call)]
|
2021-05-18 18:45:39 +01:00
|
|
|
#![deny(unreachable_pub)]
|
2022-02-14 14:24:06 +00:00
|
|
|
#![warn(clippy::all)]
|
2021-05-18 14:31:49 +01:00
|
|
|
#![deny(clippy::await_holding_lock)]
|
2022-05-30 18:30:00 +01:00
|
|
|
#![deny(clippy::cargo_common_metadata)]
|
2021-12-28 20:15:40 +00:00
|
|
|
#![deny(clippy::cast_lossless)]
|
|
|
|
#![deny(clippy::checked_conversions)]
|
|
|
|
#![warn(clippy::cognitive_complexity)]
|
2021-05-18 14:31:49 +01:00
|
|
|
#![deny(clippy::debug_assert_with_mut_call)]
|
|
|
|
#![deny(clippy::exhaustive_enums)]
|
|
|
|
#![deny(clippy::exhaustive_structs)]
|
|
|
|
#![deny(clippy::expl_impl_clone_on_copy)]
|
|
|
|
#![deny(clippy::fallible_impl_from)]
|
2021-08-17 19:17:57 +01:00
|
|
|
#![deny(clippy::implicit_clone)]
|
2021-05-18 14:31:49 +01:00
|
|
|
#![deny(clippy::large_stack_arrays)]
|
|
|
|
#![warn(clippy::manual_ok_or)]
|
2021-12-28 20:15:40 +00:00
|
|
|
#![deny(clippy::missing_docs_in_private_items)]
|
|
|
|
#![deny(clippy::missing_panics_doc)]
|
2021-06-22 02:34:40 +01:00
|
|
|
#![warn(clippy::needless_borrow)]
|
2022-05-30 18:27:53 +01:00
|
|
|
#![warn(clippy::needless_pass_by_value)]
|
|
|
|
#![warn(clippy::option_option)]
|
2021-05-18 14:31:49 +01:00
|
|
|
#![warn(clippy::rc_buffer)]
|
2021-12-28 20:15:40 +00:00
|
|
|
#![deny(clippy::ref_option_ref)]
|
|
|
|
#![warn(clippy::semicolon_if_nothing_returned)]
|
2021-05-18 14:31:49 +01:00
|
|
|
#![warn(clippy::trait_duplication_in_bounds)]
|
2021-08-06 21:20:37 +01:00
|
|
|
#![deny(clippy::unnecessary_wraps)]
|
2021-12-28 20:15:40 +00:00
|
|
|
#![warn(clippy::unseparated_literal_suffix)]
|
2021-08-25 20:23:57 +01:00
|
|
|
#![deny(clippy::unwrap_used)]
|
2022-05-30 19:07:38 +01:00
|
|
|
#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness
|
2023-01-27 12:49:39 +00:00
|
|
|
#![allow(clippy::uninlined_format_args)]
|
2022-06-23 19:14:54 +01:00
|
|
|
#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945
|
2022-11-03 15:05:14 +00:00
|
|
|
#![allow(clippy::result_large_err)] // temporary workaround for arti#587
|
2021-05-18 14:31:49 +01:00
|
|
|
"""
|
2022-05-30 17:05:21 +01:00
|
|
|
|
2022-06-24 13:14:55 +01:00
|
|
|
# ---------- list of lints to apply or disapply *in tests* ----------
|
|
|
|
|
|
|
|
TEST_LINTS = """
|
2022-06-24 13:24:00 +01:00
|
|
|
#![allow(clippy::bool_assert_comparison)]
|
|
|
|
#![allow(clippy::clone_on_copy)]
|
|
|
|
#![allow(clippy::dbg_macro)]
|
2022-06-24 13:15:49 +01:00
|
|
|
#![allow(clippy::print_stderr)]
|
|
|
|
#![allow(clippy::print_stdout)]
|
2022-10-11 14:00:07 +01:00
|
|
|
#![allow(clippy::single_char_pattern)]
|
2022-06-24 13:14:55 +01:00
|
|
|
#![allow(clippy::unwrap_used)]
|
2023-01-27 13:01:45 +00:00
|
|
|
#![allow(clippy::unchecked_duration_subtraction)]
|
2022-06-24 13:14:55 +01:00
|
|
|
"""
|
|
|
|
|
2022-05-30 17:05:21 +01:00
|
|
|
# ---------- some notes about lints we might use - NOT USED by any code here ----------
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-08-16 18:15:35 +01:00
|
|
|
SOON = """
|
2021-10-09 21:28:26 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
WISH_WE_COULD = """
|
|
|
|
#![warn(unused_crate_dependencies)]
|
2021-05-18 14:31:49 +01:00
|
|
|
"""
|
|
|
|
|
2021-05-18 18:45:39 +01:00
|
|
|
DECIDED_NOT = """
|
|
|
|
#![deny(clippy::redundant_pub_crate)]
|
2021-10-09 21:28:26 +01:00
|
|
|
#![deny(clippy::future_not_send)]
|
|
|
|
#![deny(clippy::redundant_closure_for_method_calls)]
|
|
|
|
#![deny(clippy::panic)]
|
|
|
|
#![deny(clippy::if_then_some_else_none)]
|
|
|
|
#![deny(clippy::expect_used)]
|
|
|
|
#![deny(clippy::option_if_let_else)]
|
|
|
|
#![deny(missing_debug_implementations)]
|
|
|
|
#![deny(clippy::pub_enum_variant_names)]
|
2021-05-18 18:45:39 +01:00
|
|
|
"""
|
|
|
|
|
2022-05-30 17:05:21 +01:00
|
|
|
# ---------- code for autoprocessing Rust source files ----------
|
|
|
|
|
2022-06-24 13:14:55 +01:00
|
|
|
PAT = re.compile(r'^ *#!\[(?:cfg_attr\(.*)?(allow|deny|warn)')
|
2021-05-18 18:45:39 +01:00
|
|
|
|
2022-05-31 19:03:38 +01:00
|
|
|
opts = None
|
2022-05-31 12:24:29 +01:00
|
|
|
deferred_errors = []
|
|
|
|
|
2022-08-16 18:15:35 +01:00
|
|
|
|
2022-05-31 19:14:19 +01:00
|
|
|
class ImproperFile(Exception):
|
|
|
|
def __init__(self, lno, message):
|
|
|
|
self.lno = lno
|
|
|
|
self.message = message
|
|
|
|
|
2022-08-16 18:15:35 +01:00
|
|
|
|
2022-06-24 12:55:42 +01:00
|
|
|
def filter_file(lints, inp, outp, insist):
|
2022-06-24 13:14:55 +01:00
|
|
|
in_lint_list = None
|
2022-05-31 11:49:25 +01:00
|
|
|
found_lint_list = False
|
2022-05-31 19:14:19 +01:00
|
|
|
lno = 0
|
2021-05-18 14:31:49 +01:00
|
|
|
for line in inp.readlines():
|
2022-05-31 19:14:19 +01:00
|
|
|
lno += 1
|
2022-06-24 13:14:55 +01:00
|
|
|
|
|
|
|
line_starts = None
|
|
|
|
line_ends = None
|
|
|
|
line_stripped = line.lstrip(' ')
|
|
|
|
if line_stripped.startswith("// @@ begin lint list"):
|
|
|
|
line_starts = 'main'
|
|
|
|
elif line_stripped.startswith("// @@ begin test lint list"):
|
|
|
|
line_starts = 'test'
|
|
|
|
elif line_stripped.startswith("//! <!-- @@ end lint list"):
|
|
|
|
line_ends = 'main'
|
|
|
|
elif line_stripped.startswith("//! <!-- @@ end test lint list"):
|
|
|
|
line_ends = 'test'
|
|
|
|
|
|
|
|
if line_starts:
|
2022-05-31 19:16:09 +01:00
|
|
|
if in_lint_list:
|
2022-08-16 18:15:35 +01:00
|
|
|
raise ImproperFile(
|
|
|
|
lno, 'found "@@ begin lint list" but inside lint list')
|
2022-05-31 11:49:25 +01:00
|
|
|
found_lint_list = True
|
2022-06-24 13:14:55 +01:00
|
|
|
in_lint_list = line_starts
|
|
|
|
indent = line[0: len(line) - len(line_stripped)]
|
|
|
|
elif line_ends:
|
2022-05-31 11:49:25 +01:00
|
|
|
# End delimiter is Rustdoc containing an HTML comment, because rustfmt
|
|
|
|
# *really really* hates comments that come after things.
|
|
|
|
# Finishing the automaintained block with just a blank line is too much of a hazard.
|
|
|
|
# It does end up in the output HTML from Rustdoc, but it is harmless there.
|
2022-05-31 19:16:09 +01:00
|
|
|
if not in_lint_list:
|
2022-08-16 18:15:35 +01:00
|
|
|
raise ImproperFile(
|
|
|
|
lno, 'found "@@ end lint list" but not inside lint list')
|
2022-06-24 13:14:55 +01:00
|
|
|
if in_lint_list != line_ends:
|
2022-08-16 18:15:35 +01:00
|
|
|
raise ImproperFile(lno, 'found end tag ' +
|
|
|
|
line_ends+' but expected '+in_lint_list)
|
2022-06-24 13:14:55 +01:00
|
|
|
if in_lint_list == 'test':
|
|
|
|
lints = TEST_LINTS
|
|
|
|
else:
|
|
|
|
lints = WANT_LINTS
|
2022-08-16 18:15:35 +01:00
|
|
|
for lint in lints.strip().split('\n'):
|
2022-06-24 13:14:55 +01:00
|
|
|
outp.write(indent + lint + '\n')
|
|
|
|
in_lint_list = None
|
2022-05-31 11:49:25 +01:00
|
|
|
elif in_lint_list:
|
2022-05-31 19:14:19 +01:00
|
|
|
if not PAT.match(line):
|
2022-08-16 18:15:35 +01:00
|
|
|
raise ImproperFile(
|
|
|
|
lno, 'entry in lint list does not look like a lint')
|
2022-05-31 11:49:25 +01:00
|
|
|
# do not send to output
|
|
|
|
continue
|
2021-05-18 14:31:49 +01:00
|
|
|
outp.write(line)
|
2022-05-31 19:16:09 +01:00
|
|
|
if in_lint_list:
|
2022-08-16 18:15:35 +01:00
|
|
|
raise ImproperFile(
|
|
|
|
lno, 'missing "@@ lint list" delimiter, still in lint list at EOF')
|
2022-06-24 12:55:42 +01:00
|
|
|
if insist and not found_lint_list:
|
2022-08-16 18:15:35 +01:00
|
|
|
raise ImproperFile(
|
|
|
|
lno, 'standard lint list block seems to be missing (wrong delimiters?)')
|
|
|
|
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-06-24 12:55:42 +01:00
|
|
|
def process(lints, fn, always_insist):
|
|
|
|
insist = (always_insist or
|
|
|
|
fnmatch.fnmatch(fn, 'crates/*/src/lib.rs') or
|
|
|
|
fnmatch.fnmatch(fn, 'crates/*/src/main.rs'))
|
|
|
|
|
2022-05-31 12:27:27 +01:00
|
|
|
tmp_name = fn+".tmp~"
|
2022-08-16 18:15:35 +01:00
|
|
|
outp = open(tmp_name, 'w')
|
|
|
|
inp = open(fn, 'r')
|
2022-05-31 19:14:19 +01:00
|
|
|
try:
|
2022-06-24 12:55:42 +01:00
|
|
|
filter_file(lints, inp, outp, insist)
|
2022-05-31 19:14:19 +01:00
|
|
|
except ImproperFile as e:
|
|
|
|
print('%s:%d: %s' % (fn, e.lno, e.message), file=sys.stderr)
|
|
|
|
deferred_errors.append(fn)
|
2022-08-16 18:15:35 +01:00
|
|
|
os.remove(tmp_name) # this tmp file is probably partial
|
2022-05-31 19:14:19 +01:00
|
|
|
return
|
|
|
|
|
2021-05-18 14:31:49 +01:00
|
|
|
inp.close()
|
|
|
|
outp.close()
|
2022-05-31 19:14:19 +01:00
|
|
|
|
2022-05-31 19:03:38 +01:00
|
|
|
if opts.check:
|
2022-05-31 12:24:29 +01:00
|
|
|
if subprocess.run(['diff', '-u', '--', fn, tmp_name]).returncode != 0:
|
|
|
|
deferred_errors.append(fn)
|
|
|
|
else:
|
|
|
|
shutil.move(tmp_name, fn)
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-08-16 18:15:35 +01:00
|
|
|
|
|
|
|
def main(lints, files):
|
2021-08-27 14:53:09 +01:00
|
|
|
if not os.path.exists("./crates/tor-proto/src/lib.rs"):
|
2021-05-18 14:31:49 +01:00
|
|
|
print("Run this from the top level of an arti repo.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2022-06-24 12:55:42 +01:00
|
|
|
always_insist = True
|
2021-08-18 13:56:44 +01:00
|
|
|
if not files:
|
2022-11-03 15:03:43 +00:00
|
|
|
files = subprocess.run(['find', '.', '-name', '*.rs'],
|
2022-08-16 18:15:35 +01:00
|
|
|
stdout=subprocess.PIPE, check=True).stdout
|
2022-06-24 12:55:42 +01:00
|
|
|
files = files.decode('utf-8').rstrip('\n').split('\n')
|
|
|
|
always_insist = False
|
2021-08-18 13:56:44 +01:00
|
|
|
|
2021-05-18 14:31:49 +01:00
|
|
|
for fn in files:
|
2022-06-24 12:55:42 +01:00
|
|
|
process(lints, fn, always_insist)
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-05-31 12:24:29 +01:00
|
|
|
if len(deferred_errors) > 0:
|
|
|
|
print('\n' + sys.argv[0] + ': standard lint block mismatch in the following files:\n '
|
|
|
|
+ ', '.join(deferred_errors), file=sys.stderr)
|
2022-05-31 16:54:15 +01:00
|
|
|
print('Run ' + sys.argv[0] + ' (possibly after editing it) to fix.')
|
2022-05-31 12:24:29 +01:00
|
|
|
sys.exit(1)
|
2021-05-18 14:31:49 +01:00
|
|
|
|
2022-08-16 18:15:35 +01:00
|
|
|
|
2021-05-18 14:31:49 +01:00
|
|
|
if __name__ == '__main__':
|
2022-05-31 19:03:38 +01:00
|
|
|
parser = argparse.ArgumentParser('standardise Rust lint blocks')
|
2022-06-24 13:36:18 +01:00
|
|
|
parser.add_argument('--check', action='store_true')
|
2022-06-24 12:55:42 +01:00
|
|
|
parser.add_argument('file', nargs='*')
|
2022-05-31 19:03:38 +01:00
|
|
|
opts = parser.parse_args()
|
|
|
|
|
|
|
|
main(WANT_LINTS, opts.file)
|