ensure .. and . parse as atoms

This commit is contained in:
Jana Dönszelmann 2026-04-03 15:56:52 +02:00
parent fdfc08e88b
commit bed1d5b38b
No known key found for this signature in database
2 changed files with 161 additions and 30 deletions

View file

@ -130,12 +130,14 @@ impl<'a> FileName<'a> {
}
}
let (new_segment, ext_excluding_dot) =
if let Some((segment, ext_excluding_dot)) = rsplit(segment.segment.clone(), '.') {
(segment, Some(ext_excluding_dot))
} else {
(segment.segment, None)
};
let (new_segment, ext_excluding_dot) = if let Some((segment, ext_excluding_dot)) =
rsplit(segment.segment.clone(), '.')
&& !ext_excluding_dot.is_empty()
{
(segment, Some(ext_excluding_dot))
} else {
(segment.segment, None)
};
Self {
leading_separator: segment.leading_separator,
@ -219,6 +221,13 @@ impl<'a> Path<'a> {
}
})
.verify(|i| {
// just ".." isn't valid
if i.segments.is_empty()
&& (i.filename.segment == ".." || i.filename.segment == ".")
{
return false;
}
!i.segments.is_empty()
|| i.filename.ext_excluding_dot.is_some()
|| !matches!(i.filename.leading_separator, PathSep::None)
@ -418,6 +427,152 @@ mod tests {
parse_input(input).unwrap()
}
#[test]
fn parse_twodots() {
assert_debug_snapshot!(parse(r#".."#), @r#"
Segments {
segments: [
Segment {
leading_space: Space(
"",
),
token: Atom(
Text(
"..",
),
),
},
],
trailing_space: Space(
"",
),
}
"#);
}
#[test]
fn parse_dot() {
assert_debug_snapshot!(parse(r#"."#), @r#"
Segments {
segments: [
Segment {
leading_space: Space(
"",
),
token: Atom(
Text(
".",
),
),
},
],
trailing_space: Space(
"",
),
}
"#);
}
#[test]
fn parse_parent() {
assert_debug_snapshot!(parse_path_only(r#"../foo.rs"#), @r#"
Path {
drive_excluding_colon: None,
segments: [
PathSegment {
leading_separator: None,
segment: "..",
},
],
filename: FileName {
leading_separator: Slash,
segment: "foo",
ext_excluding_dot: Some(
"rs",
),
location: None,
},
}
"#);
}
#[test]
fn parse_cwd() {
assert_debug_snapshot!(parse_path_only(r#"./foo.rs"#), @r#"
Path {
drive_excluding_colon: None,
segments: [
PathSegment {
leading_separator: None,
segment: ".",
},
],
filename: FileName {
leading_separator: Slash,
segment: "foo",
ext_excluding_dot: Some(
"rs",
),
location: None,
},
}
"#);
}
#[test]
fn parse_cwd_in_path() {
assert_debug_snapshot!(parse_path_only(r#"foo/./foo.rs"#), @r#"
Path {
drive_excluding_colon: None,
segments: [
PathSegment {
leading_separator: None,
segment: "foo",
},
PathSegment {
leading_separator: Slash,
segment: ".",
},
],
filename: FileName {
leading_separator: Slash,
segment: "foo",
ext_excluding_dot: Some(
"rs",
),
location: None,
},
}
"#);
}
#[test]
fn parse_parent_in_path() {
assert_debug_snapshot!(parse_path_only(r#"foo/../foo.rs"#), @r#"
Path {
drive_excluding_colon: None,
segments: [
PathSegment {
leading_separator: None,
segment: "foo",
},
PathSegment {
leading_separator: Slash,
segment: "..",
},
],
filename: FileName {
leading_separator: Slash,
segment: "foo",
ext_excluding_dot: Some(
"rs",
),
location: None,
},
}
"#);
}
#[test]
fn parse_path() {
assert_debug_snapshot!(parse_path_only(r#"tests/ui/impl-trait/unsized_coercion.rs"#), @r#"