Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/hir/format_args.rs')
-rw-r--r--crates/hir-def/src/hir/format_args.rs28
1 files changed, 22 insertions, 6 deletions
diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs
index 46d24bd4a6..7fc33abc7c 100644
--- a/crates/hir-def/src/hir/format_args.rs
+++ b/crates/hir-def/src/hir/format_args.rs
@@ -3,9 +3,10 @@ use std::mem;
use hir_expand::name::Name;
use rustc_dependencies::parse_format as parse;
+use stdx::TupleExt;
use syntax::{
ast::{self, IsString},
- AstToken, SmolStr, TextRange,
+ SmolStr, TextRange, TextSize,
};
use crate::hir::ExprId;
@@ -14,6 +15,7 @@ use crate::hir::ExprId;
pub struct FormatArgs {
pub template: Box<[FormatArgsPiece]>,
pub arguments: FormatArguments,
+ pub orphans: Vec<ExprId>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -170,15 +172,18 @@ pub(crate) fn parse(
mut args: FormatArgumentsCollector,
is_direct_literal: bool,
mut synth: impl FnMut(Name) -> ExprId,
+ mut record_usage: impl FnMut(Name, Option<TextRange>),
) -> FormatArgs {
- let text = s.text();
+ let text = s.text_without_quotes();
let str_style = match s.quote_offsets() {
Some(offsets) => {
let raw = u32::from(offsets.quotes.0.len()) - 1;
- (raw != 0).then_some(raw as usize)
+ // subtract 1 for the `r` prefix
+ (raw != 0).then(|| raw as usize - 1)
}
None => None,
};
+
let mut parser =
parse::Parser::new(text, str_style, fmt_snippet, false, parse::ParseMode::Format);
@@ -193,12 +198,17 @@ pub(crate) fn parse(
let is_source_literal = parser.is_source_literal;
if !parser.errors.is_empty() {
// FIXME: Diagnose
- return FormatArgs { template: Default::default(), arguments: args.finish() };
+ return FormatArgs {
+ template: Default::default(),
+ arguments: args.finish(),
+ orphans: vec![],
+ };
}
let to_span = |inner_span: parse::InnerSpan| {
is_source_literal.then(|| {
TextRange::new(inner_span.start.try_into().unwrap(), inner_span.end.try_into().unwrap())
+ - TextSize::from(str_style.map(|it| it + 1).unwrap_or(0) as u32 + 1)
})
};
@@ -230,9 +240,10 @@ pub(crate) fn parse(
Err(index)
}
}
- ArgRef::Name(name, _span) => {
+ ArgRef::Name(name, span) => {
let name = Name::new_text_dont_use(SmolStr::new(name));
if let Some((index, _)) = args.by_name(&name) {
+ record_usage(name, span);
// Name found in `args`, so we resolve it to its index.
if index < args.explicit_args().len() {
// Mark it as used, if it was an explicit argument.
@@ -246,6 +257,7 @@ pub(crate) fn parse(
// disabled (see RFC #2795)
// FIXME: Diagnose
}
+ record_usage(name.clone(), span);
Ok(args.add(FormatArgument {
kind: FormatArgumentKind::Captured(name.clone()),
// FIXME: This is problematic, we might want to synthesize a dummy
@@ -413,7 +425,11 @@ pub(crate) fn parse(
// FIXME: Diagnose
}
- FormatArgs { template: template.into_boxed_slice(), arguments: args.finish() }
+ FormatArgs {
+ template: template.into_boxed_slice(),
+ arguments: args.finish(),
+ orphans: unused.into_iter().map(TupleExt::head).collect(),
+ }
}
#[derive(Debug, Clone, PartialEq, Eq)]