Account for format_args in HiddenUnicodeCodepoints lint
This commit is contained in:
parent
c6afe82b8a
commit
ea291e5b5f
9 changed files with 82 additions and 34 deletions
|
@ -4,6 +4,7 @@ use rustc_span::{Ident, Span, Symbol};
|
|||
|
||||
use crate::Expr;
|
||||
use crate::ptr::P;
|
||||
use crate::token::LitKind;
|
||||
|
||||
// Definitions:
|
||||
//
|
||||
|
@ -45,6 +46,10 @@ pub struct FormatArgs {
|
|||
pub span: Span,
|
||||
pub template: Vec<FormatArgsPiece>,
|
||||
pub arguments: FormatArguments,
|
||||
/// The raw, un-split format string literal, with no escaping or processing.
|
||||
///
|
||||
/// Generally only useful for lints that care about the raw bytes the user wrote.
|
||||
pub uncooked_fmt_str: (LitKind, Symbol),
|
||||
}
|
||||
|
||||
/// A piece of a format template string.
|
||||
|
|
|
@ -1596,7 +1596,7 @@ fn walk_inline_asm_sym<T: MutVisitor>(
|
|||
|
||||
fn walk_format_args<T: MutVisitor>(vis: &mut T, fmt: &mut FormatArgs) {
|
||||
// FIXME: visit the template exhaustively.
|
||||
let FormatArgs { span, template: _, arguments } = fmt;
|
||||
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt;
|
||||
for FormatArgument { kind, expr } in arguments.all_args_mut() {
|
||||
match kind {
|
||||
FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
|
||||
|
|
|
@ -1061,7 +1061,7 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
|
|||
}
|
||||
|
||||
pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
|
||||
let FormatArgs { span: _, template: _, arguments } = fmt;
|
||||
let FormatArgs { span: _, template: _, arguments, uncooked_fmt_str: _ } = fmt;
|
||||
for FormatArgument { kind, expr } in arguments.all_args() {
|
||||
match kind {
|
||||
FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
|
||||
|
|
|
@ -531,6 +531,7 @@ fn expand_preparsed_asm(
|
|||
symbol: template_str,
|
||||
style: template_style,
|
||||
span: template_span,
|
||||
..
|
||||
} = {
|
||||
let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, template_expr, msg) else {
|
||||
return ExpandResult::Retry(());
|
||||
|
|
|
@ -166,7 +166,12 @@ fn make_format_args(
|
|||
|
||||
let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
|
||||
|
||||
let ExprToSpannedString { symbol: fmt_str, span: fmt_span, style: fmt_style } = {
|
||||
let ExprToSpannedString {
|
||||
symbol: fmt_str,
|
||||
span: fmt_span,
|
||||
style: fmt_style,
|
||||
uncooked_symbol: uncooked_fmt_str,
|
||||
} = {
|
||||
let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, efmt.clone(), msg) else {
|
||||
return ExpandResult::Retry(());
|
||||
};
|
||||
|
@ -584,7 +589,12 @@ fn make_format_args(
|
|||
}
|
||||
}
|
||||
|
||||
ExpandResult::Ready(Ok(FormatArgs { span: fmt_span, template, arguments: args }))
|
||||
ExpandResult::Ready(Ok(FormatArgs {
|
||||
span: fmt_span,
|
||||
template,
|
||||
arguments: args,
|
||||
uncooked_fmt_str,
|
||||
}))
|
||||
}
|
||||
|
||||
fn invalid_placeholder_type_error(
|
||||
|
|
|
@ -63,6 +63,10 @@ pub(crate) struct ExprToSpannedString {
|
|||
pub symbol: Symbol,
|
||||
pub style: ast::StrStyle,
|
||||
pub span: Span,
|
||||
/// The raw string literal, with no escaping or processing.
|
||||
///
|
||||
/// Generally only useful for lints that care about the raw bytes the user wrote.
|
||||
pub uncooked_symbol: (ast::token::LitKind, Symbol),
|
||||
}
|
||||
|
||||
/// - `Ok` is returned when the conversion to a string literal is unsuccessful,
|
||||
|
@ -100,6 +104,7 @@ pub(crate) fn expr_to_spanned_string<'a>(
|
|||
symbol: s,
|
||||
style,
|
||||
span: expr.span,
|
||||
uncooked_symbol: (token_lit.kind, token_lit.symbol),
|
||||
}));
|
||||
}
|
||||
Ok(ast::LitKind::ByteStr(..)) => {
|
||||
|
|
|
@ -82,7 +82,36 @@ impl HiddenUnicodeCodepoints {
|
|||
sub,
|
||||
});
|
||||
}
|
||||
|
||||
fn check_literal(
|
||||
&mut self,
|
||||
cx: &EarlyContext<'_>,
|
||||
text: Symbol,
|
||||
lit_kind: ast::token::LitKind,
|
||||
span: Span,
|
||||
label: &'static str,
|
||||
) {
|
||||
if !contains_text_flow_control_chars(text.as_str()) {
|
||||
return;
|
||||
}
|
||||
let (padding, point_at_inner_spans) = match lit_kind {
|
||||
// account for `"` or `'`
|
||||
ast::token::LitKind::Str | ast::token::LitKind::Char => (1, true),
|
||||
// account for `c"`
|
||||
ast::token::LitKind::CStr => (2, true),
|
||||
// account for `r###"`
|
||||
ast::token::LitKind::StrRaw(n) => (n as u32 + 2, true),
|
||||
// account for `cr###"`
|
||||
ast::token::LitKind::CStrRaw(n) => (n as u32 + 3, true),
|
||||
// suppress bad literals.
|
||||
ast::token::LitKind::Err(_) => return,
|
||||
// Be conservative just in case new literals do support these.
|
||||
_ => (0, false),
|
||||
};
|
||||
self.lint_text_direction_codepoint(cx, text, span, padding, point_at_inner_spans, label);
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for HiddenUnicodeCodepoints {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||
if let ast::AttrKind::DocComment(_, comment) = attr.kind {
|
||||
|
@ -97,32 +126,11 @@ impl EarlyLintPass for HiddenUnicodeCodepoints {
|
|||
// byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
|
||||
match &expr.kind {
|
||||
ast::ExprKind::Lit(token_lit) => {
|
||||
let text = token_lit.symbol;
|
||||
if !contains_text_flow_control_chars(text.as_str()) {
|
||||
return;
|
||||
}
|
||||
let (padding, point_at_inner_spans) = match token_lit.kind {
|
||||
// account for `"` or `'`
|
||||
ast::token::LitKind::Str | ast::token::LitKind::Char => (1, true),
|
||||
// account for `c"`
|
||||
ast::token::LitKind::CStr => (2, true),
|
||||
// account for `r###"`
|
||||
ast::token::LitKind::StrRaw(n) => (n as u32 + 2, true),
|
||||
// account for `cr###"`
|
||||
ast::token::LitKind::CStrRaw(n) => (n as u32 + 3, true),
|
||||
// suppress bad literals.
|
||||
ast::token::LitKind::Err(_) => return,
|
||||
// Be conservative just in case new literals do support these.
|
||||
_ => (0, false),
|
||||
};
|
||||
self.lint_text_direction_codepoint(
|
||||
cx,
|
||||
text,
|
||||
expr.span,
|
||||
padding,
|
||||
point_at_inner_spans,
|
||||
"literal",
|
||||
);
|
||||
self.check_literal(cx, token_lit.symbol, token_lit.kind, expr.span, "literal");
|
||||
}
|
||||
ast::ExprKind::FormatArgs(args) => {
|
||||
let (lit_kind, text) = args.uncooked_fmt_str;
|
||||
self.check_literal(cx, text, lit_kind, args.span, "format string");
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue