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:
commit
9668ae5eb8
@ -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<'_>,
|
||||
|
@ -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>,
|
||||
|
@ -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`
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`
|
||||
///
|
||||
|
@ -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:
|
||||
|
@ -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, "`")?,
|
||||
|
@ -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:
|
||||
//
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user