Rollup merge of #108726 - est31:backticks_matchmaking_tidy, r=Nilstrieb

tidy: enforce comment blocks to have an even number of backticks

After PR #108694, most unmatched backticks in `compiler/` comments have been eliminated. This PR adds a tidy lint to ensure no new unmatched backticks are added, and either addresses the lint in the remaining instances it found, or allows it.

Very often, backtick containing sections wrap around lines, for example:

```Rust
// This function takes a tuple `(Vec<String>,
// Box<[u8]>)` and transforms it into `Vec<u8>`.
```

The lint is implemented to work on top of blocks, counting each line with a `//` into a block, and counting if there are an odd or even number of backticks in the entire block, instead of looking at just a single line.
This commit is contained in:
Matthias Krüger 2023-03-12 08:13:25 +01:00 committed by GitHub
commit 9668ae5eb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 69 additions and 21 deletions

View File

@ -1052,6 +1052,7 @@ impl<'a> MethodDef<'a> {
/// ::core::hash::Hash::hash(&{ self.y }, state)
/// }
/// }
/// ```
fn expand_struct_method_body<'b>(
&self,
cx: &mut ExtCtxt<'_>,

View File

@ -438,6 +438,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
/// DW_TAG_structure_type (type of variant 1)
/// DW_TAG_structure_type (type of variant 2)
/// DW_TAG_structure_type (type of variant 3)
/// ```
struct VariantMemberInfo<'a, 'll> {
variant_index: VariantIdx,
variant_name: Cow<'a, str>,

View File

@ -41,7 +41,7 @@ impl Add for Foo {
fn main() {
let mut x: Foo = Foo(5);
x += Foo(7); // error, `+= cannot be applied to the type `Foo`
x += Foo(7); // error, `+=` cannot be applied to the type `Foo`
}
```

View File

@ -3,14 +3,14 @@ An unknown tool name was found in a scoped lint.
Erroneous code examples:
```compile_fail,E0710
#[allow(clipp::filter_map)] // error!`
#[allow(clipp::filter_map)] // error!
fn main() {
// business logic
}
```
```compile_fail,E0710
#[warn(clipp::filter_map)] // error!`
#[warn(clipp::filter_map)] // error!
fn main() {
// business logic
}

View File

@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// Here:
/// - E would be `fn(&u32) -> &u32`.
/// - S would be `fn(&u32) ->
/// - S would be `fn(&u32) -> ?T`
/// - E' is `&'!0 u32 -> &'!0 u32`
/// - S' is `&'?0 u32 -> ?T`
///

View File

@ -104,7 +104,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let (mention_influencer, influencer_point) =
if sup_origin.span().overlaps(param.param_ty_span) {
// Account for `async fn` like in `async-await/issues/issue-62097.rs`.
// The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same
// The desugaring of `async fn`s causes `sup_origin` and `param` to point at the same
// place (but with different `ctxt`, hence `overlaps` instead of `==` above).
//
// This avoids the following:

View File

@ -123,6 +123,7 @@ fn dump_matched_mir_node<'tcx, F>(
// see notes on #41697 above
let def_path =
ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
// ignore-tidy-odd-backticks the literal below is fine
write!(file, "// MIR for `{}", def_path)?;
match body.source.promoted {
None => write!(file, "`")?,

View File

@ -1886,6 +1886,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// let place = Foo::new();
// match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) }
// => { let tmp2 = place; feed(tmp2) }, ... }
// ```
//
// And an input like:
//

View File

@ -248,7 +248,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
///
/// To deal with this, we first try to normalize the self type and add the candidates for the normalized
/// self type to the list of candidates in case that succeeds. Note that we can't just eagerly return in
/// this case as projections as self types add `
/// this case as projections as self types add
// FIXME complete the unfinished sentence above
fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,

View File

@ -2220,7 +2220,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// - `BuiltinDerivedObligation` with a generator witness (A)
// - `BuiltinDerivedObligation` with a generator (A)
// - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
// - `BindingObligation` with `impl_send (Send requirement)
// - `BindingObligation` with `impl_send` (Send requirement)
//
// The first obligation in the chain is the most useful and has the generator that captured
// the type. The last generator (`outer_generator` below) has information about where the

View File

@ -18,7 +18,7 @@
//! It defines a "skeleton" of how they should be folded.
//! - `TypeSuperFoldable`. This is implemented only for each type of interest,
//! and defines the folding "skeleton" for these types.
//! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each
//! - `TypeFolder`/`FallibleTypeFolder`. One of these is implemented for each
//! folder. This defines how types of interest are folded.
//!
//! This means each fold is a mixture of (a) generic folding operations, and (b)

View File

@ -171,9 +171,9 @@ fn contains_ignore_directive(can_contain: bool, contents: &str, check: &str) ->
}
macro_rules! suppressible_tidy_err {
($err:ident, $skip:ident, $msg:expr) => {
($err:ident, $skip:ident, $msg:literal) => {
if let Directive::Deny = $skip {
$err($msg);
$err(&format!($msg));
} else {
$skip = Directive::Ignore(true);
}
@ -300,10 +300,13 @@ pub fn check(path: &Path, bad: &mut bool) {
contains_ignore_directive(can_contain, &contents, "leading-newlines");
let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright");
let mut skip_dbg = contains_ignore_directive(can_contain, &contents, "dbg");
let mut skip_odd_backticks =
contains_ignore_directive(can_contain, &contents, "odd-backticks");
let mut leading_new_lines = false;
let mut trailing_new_lines = 0;
let mut lines = 0;
let mut last_safety_comment = false;
let mut comment_block: Option<(usize, usize)> = None;
let is_test = file.components().any(|c| c.as_os_str() == "tests");
// scanning the whole file for multiple needles at once is more efficient than
// executing lines times needles separate searches.
@ -351,7 +354,7 @@ pub fn check(path: &Path, bad: &mut bool) {
suppressible_tidy_err!(
err,
skip_line_length,
&format!("line longer than {max_columns} chars")
"line longer than {max_columns} chars"
);
}
if !is_style_file && line.contains('\t') {
@ -415,15 +418,55 @@ pub fn check(path: &Path, bad: &mut bool) {
// For now only enforce in compiler
let is_compiler = || file.components().any(|c| c.as_os_str() == "compiler");
if is_compiler()
&& line.contains("//")
&& line
.chars()
.collect::<Vec<_>>()
.windows(4)
.any(|cs| matches!(cs, ['.', ' ', ' ', last] if last.is_alphabetic()))
{
err(DOUBLE_SPACE_AFTER_DOT)
if is_compiler() {
if line.contains("//")
&& line
.chars()
.collect::<Vec<_>>()
.windows(4)
.any(|cs| matches!(cs, ['.', ' ', ' ', last] if last.is_alphabetic()))
{
err(DOUBLE_SPACE_AFTER_DOT)
}
if filename.ends_with(".ftl") {
let line_backticks = trimmed.chars().filter(|ch| *ch == '`').count();
if line_backticks % 2 == 1 {
suppressible_tidy_err!(err, skip_odd_backticks, "odd number of backticks");
}
} else if trimmed.contains("//") {
let (start_line, mut backtick_count) = comment_block.unwrap_or((i + 1, 0));
let line_backticks = trimmed.chars().filter(|ch| *ch == '`').count();
let comment_text = trimmed.split("//").nth(1).unwrap();
// This check ensures that we don't lint for code that has `//` in a string literal
if line_backticks % 2 == 1 {
backtick_count += comment_text.chars().filter(|ch| *ch == '`').count();
}
comment_block = Some((start_line, backtick_count));
} else {
if let Some((start_line, backtick_count)) = comment_block.take() {
if backtick_count % 2 == 1 {
let mut err = |msg: &str| {
tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
};
let block_len = (i + 1) - start_line;
if block_len == 1 {
suppressible_tidy_err!(
err,
skip_odd_backticks,
"comment with odd number of backticks"
);
} else {
suppressible_tidy_err!(
err,
skip_odd_backticks,
"{block_len}-line comment block with odd number of backticks"
);
}
}
}
}
}
}
if leading_new_lines {
@ -441,7 +484,7 @@ pub fn check(path: &Path, bad: &mut bool) {
n => suppressible_tidy_err!(
err,
skip_trailing_newlines,
&format!("too many trailing newlines ({n})")
"too many trailing newlines ({n})"
),
};
if lines > LINES {