Auto merge of #10573 - Alexendoo:print-literal-file-macro, r=Jarcho
Ignore `file!()` macro in `print_literal`, `write_literal` changelog: [`print_literal`], [`write_literal`]: Ignore the `file!()` macro `file!()` expands to a string literal with its span set to that of the `file!()` callsite, but isn't marked as coming from an expansion. To fix this we make sure we actually find a string/char literal instead of assuming it's one and slicing It would also ignore any other macros that result in the same situation, but that shouldn't be common as `proc_macro::Span::call_site()` returns a span that is marked as from expansion Fixes #10544
This commit is contained in:
commit
d43714a101
@ -463,12 +463,18 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
|
|||||||
&& let Some(value_string) = snippet_opt(cx, arg.expr.span)
|
&& let Some(value_string) = snippet_opt(cx, arg.expr.span)
|
||||||
{
|
{
|
||||||
let (replacement, replace_raw) = match lit.kind {
|
let (replacement, replace_raw) = match lit.kind {
|
||||||
LitKind::Str | LitKind::StrRaw(_) => extract_str_literal(&value_string),
|
LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) {
|
||||||
|
Some(extracted) => extracted,
|
||||||
|
None => return,
|
||||||
|
},
|
||||||
LitKind::Char => (
|
LitKind::Char => (
|
||||||
match lit.symbol.as_str() {
|
match lit.symbol.as_str() {
|
||||||
"\"" => "\\\"",
|
"\"" => "\\\"",
|
||||||
"\\'" => "'",
|
"\\'" => "'",
|
||||||
_ => &value_string[1..value_string.len() - 1],
|
_ => match value_string.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) {
|
||||||
|
Some(stripped) => stripped,
|
||||||
|
None => return,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
.to_string(),
|
.to_string(),
|
||||||
false,
|
false,
|
||||||
@ -533,13 +539,13 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
|
|||||||
/// `r#"a"#` -> (`a`, true)
|
/// `r#"a"#` -> (`a`, true)
|
||||||
///
|
///
|
||||||
/// `"b"` -> (`b`, false)
|
/// `"b"` -> (`b`, false)
|
||||||
fn extract_str_literal(literal: &str) -> (String, bool) {
|
fn extract_str_literal(literal: &str) -> Option<(String, bool)> {
|
||||||
let (literal, raw) = match literal.strip_prefix('r') {
|
let (literal, raw) = match literal.strip_prefix('r') {
|
||||||
Some(stripped) => (stripped.trim_matches('#'), true),
|
Some(stripped) => (stripped.trim_matches('#'), true),
|
||||||
None => (literal, false),
|
None => (literal, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
(literal[1..literal.len() - 1].to_string(), raw)
|
Some((literal.strip_prefix('"')?.strip_suffix('"')?.to_string(), raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UnescapeErr {
|
enum UnescapeErr {
|
||||||
|
@ -63,7 +63,7 @@ fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Gro
|
|||||||
/// Token used to escape the following token from the macro's span rules.
|
/// Token used to escape the following token from the macro's span rules.
|
||||||
const ESCAPE_CHAR: char = '$';
|
const ESCAPE_CHAR: char = '$';
|
||||||
|
|
||||||
/// Takes a single token followed by a sequence tokens. Returns the sequence of tokens with their
|
/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
|
||||||
/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
|
/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn with_span(input: TokenStream) -> TokenStream {
|
pub fn with_span(input: TokenStream) -> TokenStream {
|
||||||
|
@ -38,4 +38,8 @@ fn main() {
|
|||||||
// named args shouldn't change anything either
|
// named args shouldn't change anything either
|
||||||
println!("{foo} {bar}", foo = "hello", bar = "world");
|
println!("{foo} {bar}", foo = "hello", bar = "world");
|
||||||
println!("{bar} {foo}", foo = "hello", bar = "world");
|
println!("{bar} {foo}", foo = "hello", bar = "world");
|
||||||
|
|
||||||
|
// The string literal from `file!()` has a callsite span that isn't marked as coming from an
|
||||||
|
// expansion
|
||||||
|
println!("file: {}", file!());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user