Refactor expand_preparsed_format_args
This commit is contained in:
parent
76b69a604e
commit
c7646d54dd
@ -772,8 +772,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||||||
// `ArgumentType` does not derive `Clone`.
|
// `ArgumentType` does not derive `Clone`.
|
||||||
let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
||||||
let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
||||||
|
|
||||||
let mut macsp = ecx.call_site();
|
let mut macsp = ecx.call_site();
|
||||||
macsp = macsp.apply_mark(ecx.current_expansion.mark);
|
macsp = macsp.apply_mark(ecx.current_expansion.mark);
|
||||||
|
|
||||||
let msg = "format argument must be a string literal";
|
let msg = "format argument must be a string literal";
|
||||||
let fmt_sp = efmt.span;
|
let fmt_sp = efmt.span;
|
||||||
let fmt = match expr_to_spanned_string(ecx, efmt, msg) {
|
let fmt = match expr_to_spanned_string(ecx, efmt, msg) {
|
||||||
@ -796,11 +798,46 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||||||
return DummyResult::raw_expr(sp);
|
return DummyResult::raw_expr(sp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_literal = match ecx.codemap().span_to_snippet(fmt_sp) {
|
let is_literal = match ecx.codemap().span_to_snippet(fmt_sp) {
|
||||||
Ok(ref s) if s.starts_with("\"") || s.starts_with("r#") => true,
|
Ok(ref s) if s.starts_with("\"") || s.starts_with("r#") => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fmt_str = &*fmt.node.0.as_str();
|
||||||
|
let str_style = match fmt.node.1 {
|
||||||
|
ast::StrStyle::Cooked => None,
|
||||||
|
ast::StrStyle::Raw(raw) => Some(raw as usize),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut parser = parse::Parser::new(fmt_str, str_style);
|
||||||
|
|
||||||
|
let mut unverified_pieces = Vec::new();
|
||||||
|
while let Some(piece) = parser.next() {
|
||||||
|
if !parser.errors.is_empty() {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
unverified_pieces.push(piece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !parser.errors.is_empty() {
|
||||||
|
let err = parser.errors.remove(0);
|
||||||
|
let sp = fmt.span.from_inner_byte_pos(err.start, err.end);
|
||||||
|
let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}",
|
||||||
|
err.description));
|
||||||
|
e.span_label(sp, err.label + " in format string");
|
||||||
|
if let Some(note) = err.note {
|
||||||
|
e.note(¬e);
|
||||||
|
}
|
||||||
|
e.emit();
|
||||||
|
return DummyResult::raw_expr(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
let arg_spans = parser.arg_places.iter()
|
||||||
|
.map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut cx = Context {
|
let mut cx = Context {
|
||||||
ecx,
|
ecx,
|
||||||
args,
|
args,
|
||||||
@ -815,42 +852,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||||||
count_positions_count: 0,
|
count_positions_count: 0,
|
||||||
count_args_index_offset: 0,
|
count_args_index_offset: 0,
|
||||||
literal: String::new(),
|
literal: String::new(),
|
||||||
pieces: Vec::new(),
|
pieces: Vec::with_capacity(unverified_pieces.len()),
|
||||||
str_pieces: Vec::new(),
|
str_pieces: Vec::with_capacity(unverified_pieces.len()),
|
||||||
all_pieces_simple: true,
|
all_pieces_simple: true,
|
||||||
macsp,
|
macsp,
|
||||||
fmtsp: fmt.span,
|
fmtsp: fmt.span,
|
||||||
invalid_refs: Vec::new(),
|
invalid_refs: Vec::new(),
|
||||||
arg_spans: Vec::new(),
|
arg_spans,
|
||||||
is_literal,
|
is_literal,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fmt_str = &*fmt.node.0.as_str();
|
|
||||||
let str_style = match fmt.node.1 {
|
|
||||||
ast::StrStyle::Cooked => None,
|
|
||||||
ast::StrStyle::Raw(raw) => Some(raw as usize),
|
|
||||||
};
|
|
||||||
let mut parser = parse::Parser::new(fmt_str, str_style);
|
|
||||||
let mut unverified_pieces = vec![];
|
|
||||||
let mut pieces = vec![];
|
|
||||||
|
|
||||||
while let Some(piece) = parser.next() {
|
|
||||||
if !parser.errors.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
unverified_pieces.push(piece);
|
|
||||||
}
|
|
||||||
|
|
||||||
cx.arg_spans = parser.arg_places.iter()
|
|
||||||
.map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// This needs to happen *after* the Parser has consumed all pieces to create all the spans
|
// This needs to happen *after* the Parser has consumed all pieces to create all the spans
|
||||||
for mut piece in unverified_pieces {
|
let pieces = unverified_pieces.into_iter().map(|mut piece| {
|
||||||
cx.verify_piece(&piece);
|
cx.verify_piece(&piece);
|
||||||
cx.resolve_name_inplace(&mut piece);
|
cx.resolve_name_inplace(&mut piece);
|
||||||
pieces.push(piece);
|
piece
|
||||||
}
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
let numbered_position_args = pieces.iter().any(|arg: &parse::Piece| {
|
let numbered_position_args = pieces.iter().any(|arg: &parse::Piece| {
|
||||||
match *arg {
|
match *arg {
|
||||||
@ -867,6 +884,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||||||
cx.build_index_map();
|
cx.build_index_map();
|
||||||
|
|
||||||
let mut arg_index_consumed = vec![0usize; cx.arg_index_map.len()];
|
let mut arg_index_consumed = vec![0usize; cx.arg_index_map.len()];
|
||||||
|
|
||||||
for piece in pieces {
|
for piece in pieces {
|
||||||
if let Some(piece) = cx.build_piece(&piece, &mut arg_index_consumed) {
|
if let Some(piece) = cx.build_piece(&piece, &mut arg_index_consumed) {
|
||||||
let s = cx.build_literal_string();
|
let s = cx.build_literal_string();
|
||||||
@ -875,18 +893,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !parser.errors.is_empty() {
|
|
||||||
let err = parser.errors.remove(0);
|
|
||||||
let sp = cx.fmtsp.from_inner_byte_pos(err.start, err.end);
|
|
||||||
let mut e = cx.ecx.struct_span_err(sp, &format!("invalid format string: {}",
|
|
||||||
err.description));
|
|
||||||
e.span_label(sp, err.label + " in format string");
|
|
||||||
if let Some(note) = err.note {
|
|
||||||
e.note(¬e);
|
|
||||||
}
|
|
||||||
e.emit();
|
|
||||||
return DummyResult::raw_expr(sp);
|
|
||||||
}
|
|
||||||
if !cx.literal.is_empty() {
|
if !cx.literal.is_empty() {
|
||||||
let s = cx.build_literal_string();
|
let s = cx.build_literal_string();
|
||||||
cx.str_pieces.push(s);
|
cx.str_pieces.push(s);
|
||||||
@ -898,24 +904,25 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||||||
|
|
||||||
// Make sure that all arguments were used and all arguments have types.
|
// Make sure that all arguments were used and all arguments have types.
|
||||||
let num_pos_args = cx.args.len() - cx.names.len();
|
let num_pos_args = cx.args.len() - cx.names.len();
|
||||||
let mut errs = vec![];
|
|
||||||
for (i, ty) in cx.arg_types.iter().enumerate() {
|
let errs = cx.arg_types
|
||||||
if ty.len() == 0 {
|
.iter()
|
||||||
if cx.count_positions.contains_key(&i) {
|
.enumerate()
|
||||||
continue;
|
.filter(|(i, ty)| ty.is_empty() && !cx.count_positions.contains_key(&i))
|
||||||
}
|
.map(|(i, _)| {
|
||||||
let msg = if i >= num_pos_args {
|
let msg = if i >= num_pos_args {
|
||||||
// named argument
|
// named argument
|
||||||
"named argument never used"
|
"named argument never used"
|
||||||
} else {
|
} else {
|
||||||
// positional argument
|
// positional argument
|
||||||
"argument never used"
|
"argument never used"
|
||||||
};
|
};
|
||||||
errs.push((cx.args[i].span, msg));
|
(cx.args[i].span, msg)
|
||||||
}
|
})
|
||||||
}
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let errs_len = errs.len();
|
let errs_len = errs.len();
|
||||||
if errs_len > 0 {
|
if !errs.is_empty() {
|
||||||
let args_used = cx.arg_types.len() - errs_len;
|
let args_used = cx.arg_types.len() - errs_len;
|
||||||
let args_unused = errs_len;
|
let args_unused = errs_len;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user