Skip to content

Commit da6f7e2

Browse files
committed
Auto merge of rust-lang#16275 - davidsemakula:ast-path-segments, r=Veykril
fix: Fix `ast::Path::segments` implementation calling `ast::Path::segments` on a qualifier currently returns all the segments of the top path instead of just the segments of the qualifier. The issue can be summarized by the simple failing test below: ```rust #[test] fn path_segments() { //use ra_ap_syntax::ast; let path: ast::Path = ...; // e.g. `ast::Path` for "foo::bar::item". let path_segments: Vec<_> = path.segments().collect(); let qualifier_segments: Vec<_> = path.qualifier().unwrap().segments().collect(); assert_eq!(path_segments.len(), qualifier_segments.len() + 1); // Fails because `LHS = RHS`. } ``` This PR: - Fixes the implementation of `ast::Path::segments` - Fixes `ast::Path::segments` callers that either implicitly relied on behavior of previous implementation or exhibited other "wrong" behavior directly related to the result of `ast::Path::segments` (all callers have been reviewed, only one required modification) - Removes unnecessary (and now unused) `ast::Path::segments` alternatives
2 parents bffafc4 + 89d6b01 commit da6f7e2

File tree

3 files changed

+27
-14
lines changed

3 files changed

+27
-14
lines changed

crates/ide-assists/src/handlers/generate_constant.rs

+16
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
5050
ty.original().display_source_code(ctx.db(), constant_module.into(), false).ok()?;
5151
let target = statement.syntax().parent()?.text_range();
5252
let path = constant_token.syntax().ancestors().find_map(ast::Path::cast)?;
53+
if path.parent_path().is_some() {
54+
cov_mark::hit!(not_last_path_segment);
55+
return None;
56+
}
5357

5458
let name_refs = path.segments().map(|s| s.name_ref());
5559
let mut outer_exists = false;
@@ -250,6 +254,18 @@ fn bar() -> i32 {
250254
}
251255
fn bar() -> i32 {
252256
foo::goo::A_CONSTANT
257+
}"#,
258+
);
259+
}
260+
261+
#[test]
262+
fn test_wont_apply_when_not_last_path_segment() {
263+
cov_mark::check!(not_last_path_segment);
264+
check_assist_not_applicable(
265+
generate_constant,
266+
r#"mod foo {}
267+
fn bar() -> i32 {
268+
foo::A_CON$0STANT::invalid_segment
253269
}"#,
254270
);
255271
}

crates/ide-db/src/imports/import_assets.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -681,11 +681,10 @@ fn path_import_candidate(
681681
Some(qualifier) => match sema.resolve_path(&qualifier) {
682682
None => {
683683
if qualifier.first_qualifier().map_or(true, |it| sema.resolve_path(&it).is_none()) {
684-
let mut qualifier = qualifier
685-
.segments_of_this_path_only_rev()
684+
let qualifier = qualifier
685+
.segments()
686686
.map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text())))
687687
.collect::<Option<Vec<_>>>()?;
688-
qualifier.reverse();
689688
ImportCandidate::Path(PathImportCandidate { qualifier: Some(qualifier), name })
690689
} else {
691690
return None;

crates/syntax/src/ast/node_ext.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -285,25 +285,23 @@ impl ast::Path {
285285
self.first_qualifier_or_self().segment()
286286
}
287287

288-
// FIXME: Check usages of Self::segments, they might be wrong because of the logic of the bloew function
289-
pub fn segments_of_this_path_only_rev(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
290-
self.qualifiers_and_self().filter_map(|it| it.segment())
291-
}
292-
293288
pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
294-
successors(self.first_segment(), |p| {
295-
p.parent_path().parent_path().and_then(|p| p.segment())
289+
let path_range = self.syntax().text_range();
290+
successors(self.first_segment(), move |p| {
291+
p.parent_path().parent_path().and_then(|p| {
292+
if path_range.contains_range(p.syntax().text_range()) {
293+
p.segment()
294+
} else {
295+
None
296+
}
297+
})
296298
})
297299
}
298300

299301
pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone {
300302
successors(self.qualifier(), |p| p.qualifier())
301303
}
302304

303-
pub fn qualifiers_and_self(&self) -> impl Iterator<Item = ast::Path> + Clone {
304-
successors(Some(self.clone()), |p| p.qualifier())
305-
}
306-
307305
pub fn top_path(&self) -> ast::Path {
308306
let mut this = self.clone();
309307
while let Some(path) = this.parent_path() {

0 commit comments

Comments
 (0)