mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-27 19:16:36 +00:00
598 lines
16 KiB
Rust
598 lines
16 KiB
Rust
use Piece::*;
|
|
|
|
use super::*;
|
|
|
|
#[track_caller]
|
|
fn same(fmt: &'static str, p: &[Piece<'static>]) {
|
|
let parser = Parser::new(fmt, None, None, false, ParseMode::Format);
|
|
assert_eq!(parser.collect::<Vec<Piece<'static>>>(), p);
|
|
}
|
|
|
|
fn fmtdflt() -> FormatSpec<'static> {
|
|
return FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "",
|
|
ty_span: None,
|
|
};
|
|
}
|
|
|
|
fn musterr(s: &str) {
|
|
let mut p = Parser::new(s, None, None, false, ParseMode::Format);
|
|
p.next();
|
|
assert!(!p.errors.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn simple() {
|
|
same("asdf", &[Lit("asdf")]);
|
|
same("a{{b", &[Lit("a"), Lit("{b")]);
|
|
same("a}}b", &[Lit("a"), Lit("}b")]);
|
|
same("a}}", &[Lit("a"), Lit("}")]);
|
|
same("}}", &[Lit("}")]);
|
|
same("\\}}", &[Lit("\\"), Lit("}")]);
|
|
}
|
|
#[test]
|
|
fn invalid01() {
|
|
musterr("{")
|
|
}
|
|
#[test]
|
|
fn invalid02() {
|
|
musterr("}")
|
|
}
|
|
#[test]
|
|
fn invalid04() {
|
|
musterr("{3a}")
|
|
}
|
|
#[test]
|
|
fn invalid05() {
|
|
musterr("{:|}")
|
|
}
|
|
#[test]
|
|
fn invalid06() {
|
|
musterr("{:>>>}")
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_position() {
|
|
musterr("{18446744073709551616}");
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_width() {
|
|
musterr("{:18446744073709551616}");
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_precision() {
|
|
musterr("{:.18446744073709551616}");
|
|
}
|
|
|
|
#[test]
|
|
fn format_empty() {
|
|
same(
|
|
"{}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: fmtdflt(),
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_tab_empty() {
|
|
let fmt_pre = r###""\t{}""###;
|
|
let fmt = "\t{}";
|
|
let parser = Parser::new(fmt, None, Some(fmt_pre.into()), false, ParseMode::Format);
|
|
assert_eq!(
|
|
parser.collect::<Vec<Piece<'static>>>(),
|
|
&[
|
|
Lit("\t"),
|
|
NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 4..4,
|
|
format: fmtdflt(),
|
|
}))
|
|
],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_open_brace_tab() {
|
|
let fmt_pre = r###""{\t""###;
|
|
let fmt = "{\t";
|
|
let mut parser = Parser::new(fmt, None, Some(fmt_pre.into()), false, ParseMode::Format);
|
|
let _ = parser.by_ref().collect::<Vec<Piece<'static>>>();
|
|
assert_eq!(parser.errors[0].span, 4..4);
|
|
}
|
|
#[test]
|
|
fn format_position() {
|
|
same(
|
|
"{3}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 2..3,
|
|
format: fmtdflt(),
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_position_nothing_else() {
|
|
same(
|
|
"{3:}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 2..3,
|
|
format: fmtdflt(),
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_named() {
|
|
same(
|
|
"{name}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentNamed("name"),
|
|
position_span: 2..6,
|
|
format: fmtdflt(),
|
|
}))],
|
|
)
|
|
}
|
|
#[test]
|
|
fn format_named_space_nothing() {
|
|
same(
|
|
"{name} {}",
|
|
&[
|
|
NextArgument(Box::new(Argument {
|
|
position: ArgumentNamed("name"),
|
|
position_span: 2..6,
|
|
format: fmtdflt(),
|
|
})),
|
|
Lit(" "),
|
|
NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 9..9,
|
|
format: fmtdflt(),
|
|
})),
|
|
],
|
|
)
|
|
}
|
|
#[test]
|
|
fn format_raw() {
|
|
let snippet = r###"r#"assertion `left {op} right` failed"#"###.into();
|
|
let source = r#"assertion `left {op} right` failed"#;
|
|
|
|
let parser = Parser::new(source, Some(1), Some(snippet), true, ParseMode::Format);
|
|
let expected = &[
|
|
Lit("assertion `left "),
|
|
NextArgument(Box::new(Argument {
|
|
position: ArgumentNamed("op"),
|
|
position_span: 20..22,
|
|
format: fmtdflt(),
|
|
})),
|
|
Lit(" right` failed"),
|
|
];
|
|
assert_eq!(parser.collect::<Vec<Piece<'static>>>(), expected);
|
|
}
|
|
#[test]
|
|
fn format_type() {
|
|
same(
|
|
"{3:x}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 2..3,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_align_fill() {
|
|
same(
|
|
"{3:>}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 2..3,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignRight,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{3:0<}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 2..3,
|
|
format: FormatSpec {
|
|
fill: Some('0'),
|
|
fill_span: Some(4..5),
|
|
align: AlignLeft,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{3:*<abcd}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 2..3,
|
|
format: FormatSpec {
|
|
fill: Some('*'),
|
|
fill_span: Some(4..5),
|
|
align: AlignLeft,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "abcd",
|
|
ty_span: Some(6..10),
|
|
},
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_counts() {
|
|
same(
|
|
"{:10x}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
precision_span: None,
|
|
width: CountIs(10),
|
|
width_span: Some(3..5),
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{:10$.10x}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountIs(10),
|
|
precision_span: Some(6..9),
|
|
width: CountIsParam(10),
|
|
width_span: Some(3..6),
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{1:0$.10x}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(1),
|
|
position_span: 2..3,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountIs(10),
|
|
precision_span: Some(6..9),
|
|
width: CountIsParam(0),
|
|
width_span: Some(4..6),
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{:.*x}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(1),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountIsStar(0),
|
|
precision_span: Some(3..5),
|
|
width: CountImplied,
|
|
width_span: None,
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{:.10$x}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountIsParam(10),
|
|
width: CountImplied,
|
|
precision_span: Some(3..7),
|
|
width_span: None,
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{:a$.b$?}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountIsName("b", 6..7),
|
|
precision_span: Some(5..8),
|
|
width: CountIsName("a", 3..4),
|
|
width_span: Some(3..5),
|
|
ty: "?",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{:.4}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountIs(4),
|
|
precision_span: Some(3..5),
|
|
width: CountImplied,
|
|
width_span: None,
|
|
ty: "",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
)
|
|
}
|
|
#[test]
|
|
fn format_flags() {
|
|
same(
|
|
"{:-}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: Some(Sign::Minus),
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
same(
|
|
"{:+#}",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..2,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: Some(Sign::Plus),
|
|
alternate: true,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "",
|
|
ty_span: None,
|
|
},
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_mixture() {
|
|
same(
|
|
"abcd {3:x} efg",
|
|
&[
|
|
Lit("abcd "),
|
|
NextArgument(Box::new(Argument {
|
|
position: ArgumentIs(3),
|
|
position_span: 7..8,
|
|
format: FormatSpec {
|
|
fill: None,
|
|
fill_span: None,
|
|
align: AlignUnknown,
|
|
sign: None,
|
|
alternate: false,
|
|
zero_pad: false,
|
|
debug_hex: None,
|
|
precision: CountImplied,
|
|
width: CountImplied,
|
|
precision_span: None,
|
|
width_span: None,
|
|
ty: "x",
|
|
ty_span: None,
|
|
},
|
|
})),
|
|
Lit(" efg"),
|
|
],
|
|
);
|
|
}
|
|
#[test]
|
|
fn format_whitespace() {
|
|
same(
|
|
"{ }",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..3,
|
|
format: fmtdflt(),
|
|
}))],
|
|
);
|
|
same(
|
|
"{ }",
|
|
&[NextArgument(Box::new(Argument {
|
|
position: ArgumentImplicitlyIs(0),
|
|
position_span: 2..4,
|
|
format: fmtdflt(),
|
|
}))],
|
|
);
|
|
}
|
|
#[test]
|
|
fn asm_linespans() {
|
|
let asm_pre = r###"r"
|
|
.intel_syntax noprefix
|
|
nop""###;
|
|
let asm = r"
|
|
.intel_syntax noprefix
|
|
nop";
|
|
let mut parser = Parser::new(asm, Some(0), Some(asm_pre.into()), false, ParseMode::InlineAsm);
|
|
assert!(parser.is_source_literal);
|
|
assert_eq!(
|
|
parser.by_ref().collect::<Vec<Piece<'static>>>(),
|
|
&[Lit("\n .intel_syntax noprefix\n nop")]
|
|
);
|
|
assert_eq!(parser.line_spans, &[2..2, 11..33, 42..45]);
|
|
}
|
|
#[test]
|
|
fn asm_concat() {
|
|
let asm_pre = r###"concat!("invalid", "_", "instruction")"###;
|
|
let asm = "invalid_instruction";
|
|
let mut parser = Parser::new(asm, None, Some(asm_pre.into()), false, ParseMode::InlineAsm);
|
|
assert!(!parser.is_source_literal);
|
|
assert_eq!(parser.by_ref().collect::<Vec<Piece<'static>>>(), &[Lit(asm)]);
|
|
assert_eq!(parser.line_spans, &[]);
|
|
}
|
|
|
|
#[test]
|
|
fn diagnostic_format_flags() {
|
|
let lit = "{thing:blah}";
|
|
let mut parser = Parser::new(lit, None, None, false, ParseMode::Diagnostic);
|
|
assert!(!parser.is_source_literal);
|
|
|
|
let [NextArgument(arg)] = &*parser.by_ref().collect::<Vec<Piece<'static>>>() else { panic!() };
|
|
|
|
assert_eq!(
|
|
**arg,
|
|
Argument {
|
|
position: ArgumentNamed("thing"),
|
|
position_span: 2..7,
|
|
format: FormatSpec { ty: ":blah", ty_span: Some(7..12), ..Default::default() },
|
|
}
|
|
);
|
|
|
|
assert_eq!(parser.line_spans, &[]);
|
|
assert!(parser.errors.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn diagnostic_format_mod() {
|
|
let lit = "{thing:+}";
|
|
let mut parser = Parser::new(lit, None, None, false, ParseMode::Diagnostic);
|
|
assert!(!parser.is_source_literal);
|
|
|
|
let [NextArgument(arg)] = &*parser.by_ref().collect::<Vec<Piece<'static>>>() else { panic!() };
|
|
|
|
assert_eq!(
|
|
**arg,
|
|
Argument {
|
|
position: ArgumentNamed("thing"),
|
|
position_span: 2..7,
|
|
format: FormatSpec { ty: ":+", ty_span: Some(7..9), ..Default::default() },
|
|
}
|
|
);
|
|
|
|
assert_eq!(parser.line_spans, &[]);
|
|
assert!(parser.errors.is_empty());
|
|
}
|