mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-19 02:55:20 +00:00
Remove source path from parser errors (#9322)
## Summary I always found it odd that we had to pass this in, since it's really higher-level context for the error. The awkwardness is further evidenced by the fact that we pass in fake values everywhere (even outside of tests). The source path isn't actually used to display the error; it's only accessed elsewhere to _re-display_ the error in certain cases. This PR modifies to instead pass the path directly in those cases.
This commit is contained in:
parent
eb9a1bc5f1
commit
e80260a3c5
45 changed files with 623 additions and 714 deletions
|
@ -54,126 +54,126 @@ mod tests {
|
|||
#[test]
|
||||
fn test_assign_name() {
|
||||
let source = "x = (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_tuple() {
|
||||
let source = "(x, y) = (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_list() {
|
||||
let source = "[x, y] = (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_attribute() {
|
||||
let source = "x.y = (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_subscript() {
|
||||
let source = "x[y] = (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_starred() {
|
||||
let source = "(x, *y) = (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_for() {
|
||||
let source = "for x in (1, 2, 3): pass";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_list_comp() {
|
||||
let source = "x = [y for y in (1, 2, 3)]";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_set_comp() {
|
||||
let source = "x = {y for y in (1, 2, 3)}";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_with() {
|
||||
let source = "with 1 as x: pass";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_named_expr() {
|
||||
let source = "if x:= 1: pass";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ann_assign_name() {
|
||||
let source = "x: int = 1";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aug_assign_name() {
|
||||
let source = "x += 1";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aug_assign_attribute() {
|
||||
let source = "x.y += (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aug_assign_subscript() {
|
||||
let source = "x[y] += (1, 2, 3)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_del_name() {
|
||||
let source = "del x";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_del_attribute() {
|
||||
let source = "del x.y";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_del_subscript() {
|
||||
let source = "del x[y]";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ mod tests {
|
|||
$(
|
||||
#[test]
|
||||
fn $name() {
|
||||
let parse_ast = crate::parser::parse_suite($code, "<test>");
|
||||
let parse_ast = crate::parser::parse_suite($code, );
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
)*
|
||||
|
@ -179,7 +179,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn function_parse_error(src: &str) -> LexicalErrorType {
|
||||
let parse_ast = parse_suite(src, "<test>");
|
||||
let parse_ast = parse_suite(src);
|
||||
parse_ast
|
||||
.map_err(|e| match e.error {
|
||||
ParseErrorType::Lexical(e) => e,
|
||||
|
|
|
@ -100,343 +100,322 @@ mod tests {
|
|||
// Regression test: https://github.com/astral-sh/ruff/issues/6895
|
||||
#[test]
|
||||
fn err_literal_assignment() {
|
||||
let ast = parse_suite(r"5 = 3", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"5 = 3");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
// This test previously passed before the assignment operator checking
|
||||
// above, but we include it here for good measure.
|
||||
#[test]
|
||||
fn err_assignment_expr() {
|
||||
let ast = parse_suite(r"(5 := 3)", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: UnrecognizedToken(
|
||||
ColonEqual,
|
||||
None,
|
||||
),
|
||||
offset: 3,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(5 := 3)");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: UnrecognizedToken(
|
||||
ColonEqual,
|
||||
None,
|
||||
),
|
||||
offset: 3,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_literal_augment_assignment() {
|
||||
let ast = parse_suite(r"5 += 3", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"5 += 3");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_literal_annotation_assignment() {
|
||||
let ast = parse_suite(r"(5): int = 3", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(5): int = 3");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
// Now we exhaustively test all possible cases where assignment can fail.
|
||||
|
||||
#[test]
|
||||
fn err_bool_op() {
|
||||
let ast = parse_suite(r"x or y = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"x or y = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_named_expr() {
|
||||
let ast = parse_suite(r"(x := 5) = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(x := 5) = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_bin_op() {
|
||||
let ast = parse_suite(r"x + y = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"x + y = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_unary_op() {
|
||||
let ast = parse_suite(r"-x = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"-x = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_lambda() {
|
||||
let ast = parse_suite(r"(lambda _: 1) = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(lambda _: 1) = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_if_exp() {
|
||||
let ast = parse_suite(r"a if b else c = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"a if b else c = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_dict() {
|
||||
let ast = parse_suite(r"{'a':5} = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"{'a':5} = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_set() {
|
||||
let ast = parse_suite(r"{a} = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"{a} = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_list_comp() {
|
||||
let ast = parse_suite(r"[x for x in xs] = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"[x for x in xs] = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_set_comp() {
|
||||
let ast = parse_suite(r"{x for x in xs} = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"{x for x in xs} = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_dict_comp() {
|
||||
let ast = parse_suite(r"{x: x*2 for x in xs} = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"{x: x*2 for x in xs} = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_generator_exp() {
|
||||
let ast = parse_suite(r"(x for x in xs) = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(x for x in xs) = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_await() {
|
||||
let ast = parse_suite(r"await x = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"await x = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_yield() {
|
||||
let ast = parse_suite(r"(yield x) = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(yield x) = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_yield_from() {
|
||||
let ast = parse_suite(r"(yield from xs) = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(yield from xs) = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_compare() {
|
||||
let ast = parse_suite(r"a < b < c = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"a < b < c = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_call() {
|
||||
let ast = parse_suite(r"foo() = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"foo() = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -452,194 +431,182 @@ Err(
|
|||
// is coupled.
|
||||
//
|
||||
// See: https://docs.python.org/3/library/ast.html#ast.FormattedValue
|
||||
let ast = parse_suite(r#"f"{quux}" = 42"#, "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r#"f"{quux}" = 42"#);
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_fstring() {
|
||||
let ast = parse_suite(r#"f"{foo} and {bar}" = 42"#, "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r#"f"{foo} and {bar}" = 42"#);
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_string_literal() {
|
||||
let ast = parse_suite(r#""foo" = 42"#, "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r#""foo" = 42"#);
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_bytes_literal() {
|
||||
let ast = parse_suite(r#"b"foo" = 42"#, "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r#"b"foo" = 42"#);
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_number_literal() {
|
||||
let ast = parse_suite(r"123 = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"123 = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_boolean_literal() {
|
||||
let ast = parse_suite(r"True = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"True = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_none_literal() {
|
||||
let ast = parse_suite(r"None = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"None = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_ellipsis_literal() {
|
||||
let ast = parse_suite(r"... = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"... = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 0,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_starred() {
|
||||
let ast = parse_suite(r"*foo() = 42", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"*foo() = 42");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 1,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_list() {
|
||||
let ast = parse_suite(r"[x, foo(), y] = [42, 42, 42]", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 4,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"[x, foo(), y] = [42, 42, 42]");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 4,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_list_nested() {
|
||||
let ast = parse_suite(r"[[a, b], [[42]], d] = [[1, 2], [[3]], 4]", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 11,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"[[a, b], [[42]], d] = [[1, 2], [[3]], 4]");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 11,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_tuple() {
|
||||
let ast = parse_suite(r"(x, foo(), y) = (42, 42, 42)", "<test>");
|
||||
insta::assert_debug_snapshot!(ast, @r#"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 4,
|
||||
source_path: "<test>",
|
||||
},
|
||||
)
|
||||
"#);
|
||||
let ast = parse_suite(r"(x, foo(), y) = (42, 42, 42)");
|
||||
insta::assert_debug_snapshot!(ast, @r###"
|
||||
Err(
|
||||
ParseError {
|
||||
error: Lexical(
|
||||
AssignmentError,
|
||||
),
|
||||
offset: 4,
|
||||
},
|
||||
)
|
||||
"###);
|
||||
}
|
||||
|
||||
// This last group of tests checks that assignments we expect to be parsed
|
||||
|
@ -647,25 +614,25 @@ Err(
|
|||
|
||||
#[test]
|
||||
fn ok_starred() {
|
||||
let ast = parse_suite(r"*foo = 42", "<test>");
|
||||
let ast = parse_suite(r"*foo = 42");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_list() {
|
||||
let ast = parse_suite(r"[x, y, z] = [1, 2, 3]", "<test>");
|
||||
let ast = parse_suite(r"[x, y, z] = [1, 2, 3]");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_tuple() {
|
||||
let ast = parse_suite(r"(x, y, z) = (1, 2, 3)", "<test>");
|
||||
let ast = parse_suite(r"(x, y, z) = (1, 2, 3)");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_subscript_normal() {
|
||||
let ast = parse_suite(r"x[0] = 42", "<test>");
|
||||
let ast = parse_suite(r"x[0] = 42");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
|
@ -673,13 +640,13 @@ Err(
|
|||
// doesn't fail parsing.
|
||||
#[test]
|
||||
fn ok_subscript_weird() {
|
||||
let ast = parse_suite(r"5[0] = 42", "<test>");
|
||||
let ast = parse_suite(r"5[0] = 42");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_slice_normal() {
|
||||
let ast = parse_suite(r"x[1:2] = [42]", "<test>");
|
||||
let ast = parse_suite(r"x[1:2] = [42]");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
|
@ -687,13 +654,13 @@ Err(
|
|||
// doesn't fail parsing.
|
||||
#[test]
|
||||
fn ok_slice_weird() {
|
||||
let ast = parse_suite(r"5[1:2] = [42]", "<test>");
|
||||
let ast = parse_suite(r"5[1:2] = [42]");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_attribute_normal() {
|
||||
let ast = parse_suite(r"foo.bar = 42", "<test>");
|
||||
let ast = parse_suite(r"foo.bar = 42");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
|
@ -701,13 +668,13 @@ Err(
|
|||
// it doesn't fail parsing.
|
||||
#[test]
|
||||
fn ok_attribute_weird() {
|
||||
let ast = parse_suite(r#""foo".y = 42"#, "<test>");
|
||||
let ast = parse_suite(r#""foo".y = 42"#);
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_name() {
|
||||
let ast = parse_suite(r"foo = 42", "<test>");
|
||||
let ast = parse_suite(r"foo = 42");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
|
@ -720,13 +687,13 @@ Err(
|
|||
|
||||
let src = r"!foo = 42";
|
||||
let tokens = crate::lexer::lex(src, Mode::Ipython);
|
||||
let ast = crate::parse_tokens(tokens, src, Mode::Ipython, "<test>");
|
||||
let ast = crate::parse_tokens(tokens, src, Mode::Ipython);
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ok_assignment_expr() {
|
||||
let ast = parse_suite(r"(x := 5)", "<test>");
|
||||
let ast = parse_suite(r"(x := 5)");
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
//! return bool(i & 1)
|
||||
//! "#;
|
||||
//! let tokens = lex(python_source, Mode::Module);
|
||||
//! let ast = parse_tokens(tokens, python_source, Mode::Module, "<embedded>");
|
||||
//! let ast = parse_tokens(tokens, python_source, Mode::Module);
|
||||
//!
|
||||
//! assert!(ast.is_ok());
|
||||
//! ```
|
||||
|
@ -100,7 +100,7 @@
|
|||
//! def is_odd(i):
|
||||
//! return bool(i & 1)
|
||||
//! "#;
|
||||
//! let ast = parse_suite(python_source, "<embedded>");
|
||||
//! let ast = parse_suite(python_source);
|
||||
//!
|
||||
//! assert!(ast.is_ok());
|
||||
//! ```
|
||||
|
@ -148,7 +148,6 @@ pub fn tokenize(contents: &str, mode: Mode) -> Vec<LexResult> {
|
|||
pub fn parse_program_tokens(
|
||||
lxr: Vec<LexResult>,
|
||||
source: &str,
|
||||
source_path: &str,
|
||||
is_jupyter_notebook: bool,
|
||||
) -> anyhow::Result<Suite, ParseError> {
|
||||
let mode = if is_jupyter_notebook {
|
||||
|
@ -156,7 +155,7 @@ pub fn parse_program_tokens(
|
|||
} else {
|
||||
Mode::Module
|
||||
};
|
||||
match parse_tokens(lxr, source, mode, source_path)? {
|
||||
match parse_tokens(lxr, source, mode)? {
|
||||
Mod::Module(m) => Ok(m.body),
|
||||
Mod::Expression(_) => unreachable!("Mode::Module doesn't return other variant"),
|
||||
}
|
||||
|
@ -379,7 +378,7 @@ mod tests {
|
|||
#[test]
|
||||
fn extract_cmp_op_location() -> Result<()> {
|
||||
let contents = "x == 1";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
@ -389,7 +388,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let contents = "x != 1";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
@ -399,7 +398,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let contents = "x is 1";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
@ -409,7 +408,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let contents = "x is not 1";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
@ -419,7 +418,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let contents = "x in 1";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
@ -429,7 +428,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let contents = "x not in 1";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
@ -439,7 +438,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let contents = "x != (1 is not 2)";
|
||||
let expr = parse_expression(contents, "<filename>")?;
|
||||
let expr = parse_expression(contents)?;
|
||||
assert_eq!(
|
||||
locate_cmp_ops(&expr, contents),
|
||||
vec![LocatedCmpOp::new(
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
//! [Abstract Syntax Tree]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
|
||||
//! [`Mode`]: crate::mode
|
||||
|
||||
use std::{fmt, iter};
|
||||
|
||||
use itertools::Itertools;
|
||||
pub(super) use lalrpop_util::ParseError as LalrpopError;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
@ -51,19 +49,19 @@ use ruff_python_ast::{
|
|||
///
|
||||
/// print(foo())
|
||||
/// "#;
|
||||
/// let program = parser::parse_program(source, "<embedded>");
|
||||
/// let program = parser::parse_program(source);
|
||||
/// assert!(program.is_ok());
|
||||
/// ```
|
||||
pub fn parse_program(source: &str, source_path: &str) -> Result<ModModule, ParseError> {
|
||||
pub fn parse_program(source: &str) -> Result<ModModule, ParseError> {
|
||||
let lexer = lex(source, Mode::Module);
|
||||
match parse_tokens(lexer, source, Mode::Module, source_path)? {
|
||||
match parse_tokens(lexer, source, Mode::Module)? {
|
||||
Mod::Module(m) => Ok(m),
|
||||
Mod::Expression(_) => unreachable!("Mode::Module doesn't return other variant"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_suite(source: &str, source_path: &str) -> Result<Suite, ParseError> {
|
||||
parse_program(source, source_path).map(|m| m.body)
|
||||
pub fn parse_suite(source: &str) -> Result<Suite, ParseError> {
|
||||
parse_program(source).map(|m| m.body)
|
||||
}
|
||||
|
||||
/// Parses a single Python expression.
|
||||
|
@ -77,14 +75,14 @@ pub fn parse_suite(source: &str, source_path: &str) -> Result<Suite, ParseError>
|
|||
///
|
||||
/// ```
|
||||
/// use ruff_python_parser as parser;
|
||||
/// let expr = parser::parse_expression("1 + 2", "<embedded>");
|
||||
/// let expr = parser::parse_expression("1 + 2");
|
||||
///
|
||||
/// assert!(expr.is_ok());
|
||||
///
|
||||
/// ```
|
||||
pub fn parse_expression(source: &str, source_path: &str) -> Result<Expr, ParseError> {
|
||||
pub fn parse_expression(source: &str) -> Result<Expr, ParseError> {
|
||||
let lexer = lex(source, Mode::Expression);
|
||||
match parse_tokens(lexer, source, Mode::Expression, source_path)? {
|
||||
match parse_tokens(lexer, source, Mode::Expression)? {
|
||||
Mod::Expression(expression) => Ok(*expression.body),
|
||||
Mod::Module(_m) => unreachable!("Mode::Expression doesn't return other variant"),
|
||||
}
|
||||
|
@ -104,16 +102,12 @@ pub fn parse_expression(source: &str, source_path: &str) -> Result<Expr, ParseEr
|
|||
/// use ruff_python_parser::{parse_expression_starts_at};
|
||||
/// # use ruff_text_size::TextSize;
|
||||
///
|
||||
/// let expr = parse_expression_starts_at("1 + 2", "<embedded>", TextSize::from(400));
|
||||
/// let expr = parse_expression_starts_at("1 + 2", TextSize::from(400));
|
||||
/// assert!(expr.is_ok());
|
||||
/// ```
|
||||
pub fn parse_expression_starts_at(
|
||||
source: &str,
|
||||
source_path: &str,
|
||||
offset: TextSize,
|
||||
) -> Result<Expr, ParseError> {
|
||||
pub fn parse_expression_starts_at(source: &str, offset: TextSize) -> Result<Expr, ParseError> {
|
||||
let lexer = lex_starts_at(source, Mode::Module, offset);
|
||||
match parse_tokens(lexer, source, Mode::Expression, source_path)? {
|
||||
match parse_tokens(lexer, source, Mode::Expression)? {
|
||||
Mod::Expression(expression) => Ok(*expression.body),
|
||||
Mod::Module(_m) => unreachable!("Mode::Expression doesn't return other variant"),
|
||||
}
|
||||
|
@ -133,7 +127,7 @@ pub fn parse_expression_starts_at(
|
|||
/// ```
|
||||
/// use ruff_python_parser::{Mode, parse};
|
||||
///
|
||||
/// let expr = parse("1 + 2", Mode::Expression, "<embedded>");
|
||||
/// let expr = parse("1 + 2", Mode::Expression);
|
||||
/// assert!(expr.is_ok());
|
||||
/// ```
|
||||
///
|
||||
|
@ -148,7 +142,7 @@ pub fn parse_expression_starts_at(
|
|||
/// def greet(self):
|
||||
/// print("Hello, world!")
|
||||
/// "#;
|
||||
/// let program = parse(source, Mode::Module, "<embedded>");
|
||||
/// let program = parse(source, Mode::Module);
|
||||
/// assert!(program.is_ok());
|
||||
/// ```
|
||||
///
|
||||
|
@ -162,11 +156,11 @@ pub fn parse_expression_starts_at(
|
|||
/// ?str.replace
|
||||
/// !ls
|
||||
/// "#;
|
||||
/// let program = parse(source, Mode::Ipython, "<embedded>");
|
||||
/// let program = parse(source, Mode::Ipython);
|
||||
/// assert!(program.is_ok());
|
||||
/// ```
|
||||
pub fn parse(source: &str, mode: Mode, source_path: &str) -> Result<Mod, ParseError> {
|
||||
parse_starts_at(source, mode, source_path, TextSize::default())
|
||||
pub fn parse(source: &str, mode: Mode) -> Result<Mod, ParseError> {
|
||||
parse_starts_at(source, mode, TextSize::default())
|
||||
}
|
||||
|
||||
/// Parse the given Python source code using the specified [`Mode`] and [`TextSize`].
|
||||
|
@ -189,17 +183,12 @@ pub fn parse(source: &str, mode: Mode, source_path: &str) -> Result<Mod, ParseEr
|
|||
///
|
||||
/// print(fib(42))
|
||||
/// "#;
|
||||
/// let program = parse_starts_at(source, Mode::Module, "<embedded>", TextSize::from(0));
|
||||
/// let program = parse_starts_at(source, Mode::Module, TextSize::from(0));
|
||||
/// assert!(program.is_ok());
|
||||
/// ```
|
||||
pub fn parse_starts_at(
|
||||
source: &str,
|
||||
mode: Mode,
|
||||
source_path: &str,
|
||||
offset: TextSize,
|
||||
) -> Result<Mod, ParseError> {
|
||||
pub fn parse_starts_at(source: &str, mode: Mode, offset: TextSize) -> Result<Mod, ParseError> {
|
||||
let lxr = lexer::lex_starts_at(source, mode, offset);
|
||||
parse_tokens(lxr, source, mode, source_path)
|
||||
parse_tokens(lxr, source, mode)
|
||||
}
|
||||
|
||||
/// Parse an iterator of [`LexResult`]s using the specified [`Mode`].
|
||||
|
@ -215,14 +204,13 @@ pub fn parse_starts_at(
|
|||
/// use ruff_python_parser::{lexer::lex, Mode, parse_tokens};
|
||||
///
|
||||
/// let source = "1 + 2";
|
||||
/// let expr = parse_tokens(lex(source, Mode::Expression), source, Mode::Expression, "<embedded>");
|
||||
/// let expr = parse_tokens(lex(source, Mode::Expression), source, Mode::Expression);
|
||||
/// assert!(expr.is_ok());
|
||||
/// ```
|
||||
pub fn parse_tokens(
|
||||
lxr: impl IntoIterator<Item = LexResult>,
|
||||
source: &str,
|
||||
mode: Mode,
|
||||
source_path: &str,
|
||||
) -> Result<Mod, ParseError> {
|
||||
let lxr = lxr.into_iter();
|
||||
|
||||
|
@ -230,7 +218,6 @@ pub fn parse_tokens(
|
|||
lxr.filter_ok(|(tok, _)| !matches!(tok, Tok::Comment { .. } | Tok::NonLogicalNewline)),
|
||||
source,
|
||||
mode,
|
||||
source_path,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -239,35 +226,33 @@ pub fn parse_ok_tokens(
|
|||
lxr: impl IntoIterator<Item = Spanned>,
|
||||
source: &str,
|
||||
mode: Mode,
|
||||
source_path: &str,
|
||||
) -> Result<Mod, ParseError> {
|
||||
let lxr = lxr
|
||||
.into_iter()
|
||||
.filter(|(tok, _)| !matches!(tok, Tok::Comment { .. } | Tok::NonLogicalNewline));
|
||||
let marker_token = (Tok::start_marker(mode), TextRange::default());
|
||||
let lexer = iter::once(marker_token)
|
||||
let lexer = std::iter::once(marker_token)
|
||||
.chain(lxr)
|
||||
.map(|(t, range)| (range.start(), t, range.end()));
|
||||
python::TopParser::new()
|
||||
.parse(source, mode, lexer)
|
||||
.map_err(|e| parse_error_from_lalrpop(e, source_path))
|
||||
.map_err(parse_error_from_lalrpop)
|
||||
}
|
||||
|
||||
fn parse_filtered_tokens(
|
||||
lxr: impl IntoIterator<Item = LexResult>,
|
||||
source: &str,
|
||||
mode: Mode,
|
||||
source_path: &str,
|
||||
) -> Result<Mod, ParseError> {
|
||||
let marker_token = (Tok::start_marker(mode), TextRange::default());
|
||||
let lexer = iter::once(Ok(marker_token)).chain(lxr);
|
||||
let lexer = std::iter::once(Ok(marker_token)).chain(lxr);
|
||||
python::TopParser::new()
|
||||
.parse(
|
||||
source,
|
||||
mode,
|
||||
lexer.map_ok(|(t, range)| (range.start(), t, range.end())),
|
||||
)
|
||||
.map_err(|e| parse_error_from_lalrpop(e, source_path))
|
||||
.map_err(parse_error_from_lalrpop)
|
||||
}
|
||||
|
||||
/// Represents represent errors that occur during parsing and are
|
||||
|
@ -277,7 +262,6 @@ fn parse_filtered_tokens(
|
|||
pub struct ParseError {
|
||||
pub error: ParseErrorType,
|
||||
pub offset: TextSize,
|
||||
pub source_path: String,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ParseError {
|
||||
|
@ -294,7 +278,7 @@ impl std::error::Error for ParseError {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
impl std::fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -324,28 +308,20 @@ pub enum ParseErrorType {
|
|||
impl std::error::Error for ParseErrorType {}
|
||||
|
||||
// Convert `lalrpop_util::ParseError` to our internal type
|
||||
fn parse_error_from_lalrpop(
|
||||
err: LalrpopError<TextSize, Tok, LexicalError>,
|
||||
source_path: &str,
|
||||
) -> ParseError {
|
||||
let source_path = source_path.to_owned();
|
||||
|
||||
fn parse_error_from_lalrpop(err: LalrpopError<TextSize, Tok, LexicalError>) -> ParseError {
|
||||
match err {
|
||||
// TODO: Are there cases where this isn't an EOF?
|
||||
LalrpopError::InvalidToken { location } => ParseError {
|
||||
error: ParseErrorType::Eof,
|
||||
offset: location,
|
||||
source_path,
|
||||
},
|
||||
LalrpopError::ExtraToken { token } => ParseError {
|
||||
error: ParseErrorType::ExtraToken(token.1),
|
||||
offset: token.0,
|
||||
source_path,
|
||||
},
|
||||
LalrpopError::User { error } => ParseError {
|
||||
error: ParseErrorType::Lexical(error.error),
|
||||
offset: error.location,
|
||||
source_path,
|
||||
},
|
||||
LalrpopError::UnrecognizedToken { token, expected } => {
|
||||
// Hacky, but it's how CPython does it. See PyParser_AddToken,
|
||||
|
@ -354,7 +330,6 @@ fn parse_error_from_lalrpop(
|
|||
ParseError {
|
||||
error: ParseErrorType::UnrecognizedToken(token.1, expected),
|
||||
offset: token.0,
|
||||
source_path,
|
||||
}
|
||||
}
|
||||
LalrpopError::UnrecognizedEof { location, expected } => {
|
||||
|
@ -364,13 +339,11 @@ fn parse_error_from_lalrpop(
|
|||
ParseError {
|
||||
error: ParseErrorType::Lexical(LexicalErrorType::IndentationError),
|
||||
offset: location,
|
||||
source_path,
|
||||
}
|
||||
} else {
|
||||
ParseError {
|
||||
error: ParseErrorType::Eof,
|
||||
offset: location,
|
||||
source_path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -629,63 +602,63 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parse_empty() {
|
||||
let parse_ast = parse_suite("", "<test>").unwrap();
|
||||
let parse_ast = parse_suite("").unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_string() {
|
||||
let source = "'Hello world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_string() {
|
||||
let source = "f'Hello world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_hello() {
|
||||
let source = "print('Hello world')";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_2() {
|
||||
let source = "print('Hello world', 2)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_kwargs() {
|
||||
let source = "my_func('positional', keyword=2)";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_if_elif_else() {
|
||||
let source = "if 1: 10\nelif 2: 20\nelse: 30";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_lambda() {
|
||||
let source = "lambda x, y: x * y"; // lambda(x, y): x * y";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_lambda_no_args() {
|
||||
let source = "lambda: 1";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -693,7 +666,7 @@ mod tests {
|
|||
fn test_parse_tuples() {
|
||||
let source = "a, b = 4, 5";
|
||||
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -705,7 +678,7 @@ class Foo(A, B):
|
|||
def method_with_default(self, arg='default'):
|
||||
pass
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -736,7 +709,7 @@ class Foo[**P](): ...
|
|||
class Foo[X, Y: str, *U, **P]():
|
||||
pass
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
#[test]
|
||||
fn test_parse_function_definition() {
|
||||
|
@ -762,76 +735,76 @@ def func[**P](*args: P.args, **kwargs: P.kwargs):
|
|||
def func[T, U: str, *Ts, **P]():
|
||||
pass
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_dict_comprehension() {
|
||||
let source = "{x1: x2 for y in z}";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_list_comprehension() {
|
||||
let source = "[x for y in z]";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_double_list_comprehension() {
|
||||
let source = "[x for y, y2 in z for a in b if a < 5 if a > 10]";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_generator_comprehension() {
|
||||
let source = "(x for y in z)";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_named_expression_generator_comprehension() {
|
||||
let source = "(x := y + 1 for y in z)";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_if_else_generator_comprehension() {
|
||||
let source = "(x if y else y for y in z)";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_bool_op_or() {
|
||||
let source = "x or y";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_bool_op_and() {
|
||||
let source = "x and y";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice() {
|
||||
let source = "x[1:2:3]";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_named_expression() {
|
||||
let source = "(x := ( y * z ))";
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -865,7 +838,7 @@ with (0 as a,): pass
|
|||
with (0 as a, 1 as b): pass
|
||||
with (0 as a, 1 as b,): pass
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -889,7 +862,7 @@ with (yield from a): pass
|
|||
with ((yield)): pass
|
||||
with ((yield from a)): pass
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -912,7 +885,7 @@ with ((yield from a)): pass
|
|||
"with a := 0 as x: pass",
|
||||
"with (a := 0 as x): pass",
|
||||
] {
|
||||
assert!(parse_suite(source, "<test>").is_err());
|
||||
assert!(parse_suite(source).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -924,7 +897,7 @@ array[0, *indexes, -1] = array_slice
|
|||
array[*indexes_to_select, *indexes_to_select]
|
||||
array[3:5, *indexes_to_select]
|
||||
";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -937,7 +910,7 @@ array[3:5, *indexes_to_select]
|
|||
("OFFSET %d" % offset) if offset else None,
|
||||
)
|
||||
)"#;
|
||||
let parse_ast = parse_expression(source, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -950,7 +923,6 @@ except TypeError as e:
|
|||
print(f'caught {type(e)}')
|
||||
except OSError as e:
|
||||
print(f'caught {type(e)}')",
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -966,7 +938,6 @@ except* TypeError as e:
|
|||
print(f'caught {type(e)} with nested {e.exceptions}')
|
||||
except* OSError as e:
|
||||
print(f'caught {type(e)} with nested {e.exceptions}')"#,
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -974,7 +945,7 @@ except* OSError as e:
|
|||
|
||||
#[test]
|
||||
fn test_dict_unpacking() {
|
||||
let parse_ast = parse_expression(r#"{"a": "b", **c, "d": "e"}"#, "<test>").unwrap();
|
||||
let parse_ast = parse_expression(r#"{"a": "b", **c, "d": "e"}"#).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -982,8 +953,8 @@ except* OSError as e:
|
|||
fn test_modes() {
|
||||
let source = "a[0][1][2][3][4]";
|
||||
|
||||
assert!(parse(source, Mode::Expression, "<embedded>").is_ok());
|
||||
assert!(parse(source, Mode::Module, "<embedded>").is_ok());
|
||||
assert!(parse(source, Mode::Expression).is_ok());
|
||||
assert!(parse(source, Mode::Module).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1030,7 +1001,7 @@ type X[T] \
|
|||
type X = int; type X = str; type X = type
|
||||
class X: type X = int
|
||||
"#;
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1068,13 +1039,13 @@ type = x = 1
|
|||
x = type = 1
|
||||
lambda x: type
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_type() {
|
||||
assert!(parse_suite("a: type X = int", "<test>").is_err());
|
||||
assert!(parse_suite("lambda: type X = int", "<test>").is_err());
|
||||
assert!(parse_suite("a: type X = int").is_err());
|
||||
assert!(parse_suite("lambda: type X = int").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1099,7 +1070,7 @@ x = 10000
|
|||
x = 133333
|
||||
";
|
||||
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1125,7 +1096,7 @@ if 10 .real:
|
|||
y = 100[no]
|
||||
y = 100(no)
|
||||
";
|
||||
assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1153,7 +1124,7 @@ match match:
|
|||
match = lambda query: query == event
|
||||
print(match(12))
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1323,7 +1294,7 @@ match w := x,:
|
|||
case y as v,:
|
||||
z = 0
|
||||
"#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -1360,7 +1331,6 @@ match x, y,:
|
|||
case z:
|
||||
pass
|
||||
"#,
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -1375,7 +1345,6 @@ match x:
|
|||
case f"{y}":
|
||||
pass
|
||||
"#,
|
||||
"<test>",
|
||||
)
|
||||
.err();
|
||||
assert!(
|
||||
|
@ -1390,7 +1359,6 @@ match x:
|
|||
r"
|
||||
def args_to_tuple(*args: *Ts) -> Tuple[*Ts]: ...
|
||||
",
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -1409,7 +1377,6 @@ class Abcd:
|
|||
pass
|
||||
"
|
||||
.trim(),
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -1486,7 +1453,6 @@ foo.bar[0].baz[2].egg??
|
|||
"
|
||||
.trim(),
|
||||
Mode::Ipython,
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -1500,7 +1466,7 @@ a = 1
|
|||
"
|
||||
.trim();
|
||||
let lxr = lexer::lex_starts_at(source, Mode::Ipython, TextSize::default());
|
||||
let parse_err = parse_tokens(lxr, source, Mode::Module, "<test>").unwrap_err();
|
||||
let parse_err = parse_tokens(lxr, source, Mode::Module).unwrap_err();
|
||||
assert_eq!(
|
||||
parse_err.to_string(),
|
||||
"IPython escape commands are only allowed in `Mode::Ipython` at byte offset 6"
|
||||
|
@ -1540,7 +1506,6 @@ f"""{
|
|||
}"""
|
||||
"#
|
||||
.trim(),
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -1556,7 +1521,6 @@ u"foo" f"{bar}" "baz" " some"
|
|||
u"foo" f"bar {baz} really" u"bar" "no"
|
||||
"#
|
||||
.trim(),
|
||||
"<test>",
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
|
@ -1565,7 +1529,7 @@ u"foo" f"bar {baz} really" u"bar" "no"
|
|||
#[test]
|
||||
fn test_unicode_aliases() {
|
||||
// https://github.com/RustPython/RustPython/issues/4566
|
||||
let parse_ast = parse_suite(r#"x = "\N{BACKSPACE}another cool trick""#, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(r#"x = "\N{BACKSPACE}another cool trick""#).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@ mod tests {
|
|||
|
||||
fn string_parser_escaped_eol(eol: &str) -> Suite {
|
||||
let source = format!(r"'text \{eol}more text'");
|
||||
parse_suite(&source, "<test>").unwrap()
|
||||
parse_suite(&source).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -513,7 +513,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_parse_fstring() {
|
||||
let source = r#"f"{a}{ b }{{foo}}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_parse_fstring_nested_spec() {
|
||||
let source = r#"f"{foo:{spec}}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -529,20 +529,20 @@ mod tests {
|
|||
#[test]
|
||||
fn test_parse_fstring_not_nested_spec() {
|
||||
let source = r#"f"{foo:spec}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_empty_fstring() {
|
||||
insta::assert_debug_snapshot!(parse_suite(r#"f"""#, "<test>").unwrap());
|
||||
insta::assert_debug_snapshot!(parse_suite(r#"f"""#,).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_parse_self_documenting_base() {
|
||||
let source = r#"f"{user=}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_fstring_parse_self_documenting_base_more() {
|
||||
let source = r#"f"mix {user=} with text and {second=}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -558,13 +558,13 @@ mod tests {
|
|||
#[test]
|
||||
fn test_fstring_parse_self_documenting_format() {
|
||||
let source = r#"f"{user=:>10}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
fn parse_fstring_error(source: &str) -> FStringErrorType {
|
||||
parse_suite(source, "<test>")
|
||||
parse_suite(source)
|
||||
.map_err(|e| match e.error {
|
||||
ParseErrorType::Lexical(LexicalErrorType::FStringError(e)) => e,
|
||||
e => unreachable!("Expected FStringError: {:?}", e),
|
||||
|
@ -585,111 +585,111 @@ mod tests {
|
|||
parse_fstring_error("f'{lambda x: {x}}'"),
|
||||
LambdaWithoutParentheses
|
||||
);
|
||||
assert!(parse_suite(r#"f"{class}""#, "<test>").is_err());
|
||||
assert!(parse_suite(r#"f"{class}""#,).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fstring_not_equals() {
|
||||
let source = r#"f"{1 != 2}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fstring_equals() {
|
||||
let source = r#"f"{42 == 42}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fstring_self_doc_prec_space() {
|
||||
let source = r#"f"{x =}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fstring_self_doc_trailing_space() {
|
||||
let source = r#"f"{x= }""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fstring_yield_expr() {
|
||||
let source = r#"f"{yield}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_string_concat() {
|
||||
let source = "'Hello ' 'world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_u_string_concat_1() {
|
||||
let source = "'Hello ' u'world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_u_string_concat_2() {
|
||||
let source = "u'Hello ' 'world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_string_concat_1() {
|
||||
let source = "'Hello ' f'world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_string_concat_2() {
|
||||
let source = "'Hello ' f'world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_string_concat_3() {
|
||||
let source = "'Hello ' f'world{\"!\"}'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f_string_concat_4() {
|
||||
let source = "'Hello ' f'world{\"!\"}' 'again!'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_u_f_string_concat_1() {
|
||||
let source = "u'Hello ' f'world'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_u_f_string_concat_2() {
|
||||
let source = "u'Hello ' f'world' '!'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_string_triple_quotes_with_kind() {
|
||||
let source = "u'''Hello, world!'''";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -697,7 +697,7 @@ mod tests {
|
|||
fn test_single_quoted_byte() {
|
||||
// single quote
|
||||
let source = r##"b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'"##;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -705,7 +705,7 @@ mod tests {
|
|||
fn test_double_quoted_byte() {
|
||||
// double quote
|
||||
let source = r##"b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff""##;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -713,42 +713,42 @@ mod tests {
|
|||
fn test_escape_char_in_byte_literal() {
|
||||
// backslash does not escape
|
||||
let source = r#"b"omkmok\Xaa""#; // spell-checker:ignore omkmok
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_raw_byte_literal_1() {
|
||||
let source = r"rb'\x1z'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_raw_byte_literal_2() {
|
||||
let source = r"rb'\\'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_escape_octet() {
|
||||
let source = r"b'\43a\4\1234'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_escaped_newline() {
|
||||
let source = r#"f"\n{x}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_constant_range() {
|
||||
let source = r#"f"aaa{bbb}ccc{ddd}eee""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -756,28 +756,28 @@ mod tests {
|
|||
fn test_fstring_unescaped_newline() {
|
||||
let source = r#"f"""
|
||||
{x}""""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fstring_escaped_character() {
|
||||
let source = r#"f"\\{x}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_raw_fstring() {
|
||||
let source = r#"rf"{x}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_triple_quoted_raw_fstring() {
|
||||
let source = r#"rf"""{x}""""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
|
@ -785,14 +785,14 @@ mod tests {
|
|||
fn test_fstring_line_continuation() {
|
||||
let source = r#"rf"\
|
||||
{x}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fstring_nested_string_spec() {
|
||||
let source = r#"f"{foo:{''}}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -800,7 +800,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_parse_fstring_nested_concatenation_string_spec() {
|
||||
let source = r#"f"{foo:{'' ''}}""#;
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -809,7 +809,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_dont_panic_on_8_in_octal_escape() {
|
||||
let source = r"bold = '\038[1m'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(source).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -820,7 +820,7 @@ mod tests {
|
|||
#[test]
|
||||
fn $name() {
|
||||
let source = format!(r#""\N{{{0}}}""#, $alias);
|
||||
let parse_ast = parse_suite(&source, "<test>").unwrap();
|
||||
let parse_ast = parse_suite(&source).unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
)*
|
||||
|
|
|
@ -33,15 +33,11 @@ pub fn parse_type_annotation(
|
|||
// isn't the case, e.g., for implicit concatenations, or for annotations that contain
|
||||
// escaped quotes.
|
||||
let leading_quote = str::leading_quote(expression).unwrap();
|
||||
let expr = parse_expression_starts_at(
|
||||
value,
|
||||
"<filename>",
|
||||
range.start() + leading_quote.text_len(),
|
||||
)?;
|
||||
let expr = parse_expression_starts_at(value, range.start() + leading_quote.text_len())?;
|
||||
Ok((expr, AnnotationKind::Simple))
|
||||
} else {
|
||||
// Otherwise, consider this a "complex" annotation.
|
||||
let mut expr = parse_expression(value, "<filename>")?;
|
||||
let mut expr = parse_expression(value)?;
|
||||
relocate_expr(&mut expr, range);
|
||||
Ok((expr, AnnotationKind::Complex))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue