Skip to content

Commit 97fe64a

Browse files
bors[bot]matkladJonas Schievink
authored
Merge #8154 #8155
8154: rewrite merge use trees assist to use muatable syntax trees r=matklad a=matklad bors r+ 🤖 8155: Fix confusion between parameters and the function r=jonas-schievink a=jonas-schievink Fixes #8152 bors r+ Co-authored-by: Aleksey Kladov <[email protected]> Co-authored-by: Jonas Schievink <[email protected]>
3 parents d834306 + 9cbf09e + 2633e23 commit 97fe64a

File tree

11 files changed

+163
-90
lines changed

11 files changed

+163
-90
lines changed

crates/hir_def/src/nameres.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,23 @@ impl DefMap {
322322
(res.resolved_def, res.segment_index)
323323
}
324324

325+
pub(crate) fn resolve_path_locally(
326+
&self,
327+
db: &dyn DefDatabase,
328+
original_module: LocalModuleId,
329+
path: &ModPath,
330+
shadow: BuiltinShadowMode,
331+
) -> (PerNs, Option<usize>) {
332+
let res = self.resolve_path_fp_with_macro_single(
333+
db,
334+
ResolveMode::Other,
335+
original_module,
336+
path,
337+
shadow,
338+
);
339+
(res.resolved_def, res.segment_index)
340+
}
341+
325342
/// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
326343
///
327344
/// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns

crates/hir_def/src/nameres/path_resolution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl DefMap {
156156
}
157157
}
158158

159-
fn resolve_path_fp_with_macro_single(
159+
pub(super) fn resolve_path_fp_with_macro_single(
160160
&self,
161161
db: &dyn DefDatabase,
162162
mode: ResolveMode,

crates/hir_def/src/resolver.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ impl ModuleItemMap {
548548
path: &ModPath,
549549
) -> Option<ResolveValueResult> {
550550
let (module_def, idx) =
551-
self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
551+
self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other);
552552
match idx {
553553
None => {
554554
let value = to_value_ns(module_def)?;
@@ -578,7 +578,7 @@ impl ModuleItemMap {
578578
path: &ModPath,
579579
) -> Option<(TypeNs, Option<usize>)> {
580580
let (module_def, idx) =
581-
self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
581+
self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other);
582582
let res = to_type_ns(module_def)?;
583583
Some((res, idx))
584584
}
@@ -627,8 +627,18 @@ pub trait HasResolver: Copy {
627627

628628
impl HasResolver for ModuleId {
629629
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
630-
let def_map = self.def_map(db);
631-
Resolver::default().push_module_scope(def_map, self.local_id)
630+
let mut def_map = self.def_map(db);
631+
let mut modules = Vec::new();
632+
modules.push((def_map.clone(), self.local_id));
633+
while let Some(parent) = def_map.parent() {
634+
def_map = parent.def_map(db);
635+
modules.push((def_map.clone(), parent.local_id));
636+
}
637+
let mut resolver = Resolver::default();
638+
for (def_map, module) in modules.into_iter().rev() {
639+
resolver = resolver.push_module_scope(def_map, module);
640+
}
641+
resolver
632642
}
633643
}
634644

crates/hir_ty/src/tests/regression.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,3 +961,16 @@ fn issue_6852() {
961961
"#]],
962962
);
963963
}
964+
965+
#[test]
966+
fn param_overrides_fn() {
967+
check_types(
968+
r#"
969+
fn example(example: i32) {
970+
fn f() {}
971+
example;
972+
//^^^^^^^ i32
973+
}
974+
"#,
975+
)
976+
}

crates/ide_assists/src/handlers/merge_imports.rs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior};
2-
use syntax::{
3-
algo::{neighbor, SyntaxRewriter},
4-
ast, AstNode,
5-
};
2+
use syntax::{algo::neighbor, ast, ted, AstNode};
63

74
use crate::{
85
assist_context::{AssistContext, Assists},
@@ -24,33 +21,29 @@ use crate::{
2421
// ```
2522
pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
2623
let tree: ast::UseTree = ctx.find_node_at_offset()?;
27-
let mut rewriter = SyntaxRewriter::default();
24+
let original_parent = tree.syntax().ancestors().last()?;
25+
26+
let tree = tree.clone_for_update();
27+
let new_parent = tree.syntax().ancestors().last()?;
28+
2829
let mut offset = ctx.offset();
2930

31+
let mut imports = None;
32+
let mut uses = None;
3033
if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) {
31-
let (merged, to_delete) =
34+
let (merged, to_remove) =
3235
next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| {
3336
try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2))
3437
})?;
3538

36-
rewriter.replace_ast(&use_item, &merged);
37-
rewriter += to_delete.remove();
38-
39-
if to_delete.syntax().text_range().end() < offset {
40-
offset -= to_delete.syntax().text_range().len();
41-
}
39+
imports = Some((use_item, merged, to_remove));
4240
} else {
43-
let (merged, to_delete) =
41+
let (merged, to_remove) =
4442
next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| {
4543
try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree))
4644
})?;
4745

48-
rewriter.replace_ast(&tree, &merged);
49-
rewriter += to_delete.remove();
50-
51-
if to_delete.syntax().text_range().end() < offset {
52-
offset -= to_delete.syntax().text_range().len();
53-
}
46+
uses = Some((tree.clone(), merged, to_remove))
5447
};
5548

5649
let target = tree.syntax().text_range();
@@ -59,7 +52,23 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()
5952
"Merge imports",
6053
target,
6154
|builder| {
62-
builder.rewrite(rewriter);
55+
if let Some((to_replace, replacement, to_remove)) = imports {
56+
if to_remove.syntax().text_range().end() < offset {
57+
offset -= to_remove.syntax().text_range().len();
58+
}
59+
ted::replace(to_replace.syntax().clone(), replacement.syntax().clone());
60+
to_remove.remove();
61+
}
62+
63+
if let Some((to_replace, replacement, to_remove)) = uses {
64+
if to_remove.syntax().text_range().end() < offset {
65+
offset -= to_remove.syntax().text_range().len();
66+
}
67+
ted::replace(to_replace.syntax().clone(), replacement.syntax().clone());
68+
to_remove.remove()
69+
}
70+
71+
builder.replace(original_parent.text_range(), new_parent.to_string())
6372
},
6473
)
6574
}

crates/ide_assists/src/handlers/unmerge_use.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use syntax::{
2-
algo::SyntaxRewriter,
3-
ast::{self, edit::AstNodeEdit, VisibilityOwner},
2+
ast::{self, VisibilityOwner},
3+
ted::{self, Position},
44
AstNode, SyntaxKind,
55
};
66

@@ -22,7 +22,7 @@ use crate::{
2222
// use std::fmt::Display;
2323
// ```
2424
pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
25-
let tree: ast::UseTree = ctx.find_node_at_offset()?;
25+
let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();
2626

2727
let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
2828
if tree_list.use_trees().count() < 2 {
@@ -33,6 +33,9 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
3333
let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
3434
let path = resolve_full_path(&tree)?;
3535

36+
let old_parent_range = use_.syntax().parent()?.text_range();
37+
let new_parent = use_.syntax().parent()?;
38+
3639
let target = tree.syntax().text_range();
3740
acc.add(
3841
AssistId("unmerge_use", AssistKind::RefactorRewrite),
@@ -47,20 +50,13 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
4750
tree.rename(),
4851
tree.star_token().is_some(),
4952
),
50-
);
51-
52-
let mut rewriter = SyntaxRewriter::default();
53-
rewriter += tree.remove();
54-
rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline());
55-
if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize {
56-
rewriter.insert_after(
57-
use_.syntax(),
58-
&ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)),
59-
);
60-
}
61-
rewriter.insert_after(use_.syntax(), new_use.syntax());
62-
63-
builder.rewrite(rewriter);
53+
)
54+
.clone_for_update();
55+
56+
tree.remove();
57+
ted::insert(Position::after(use_.syntax()), new_use.syntax());
58+
59+
builder.replace(old_parent_range, new_parent.to_string());
6460
},
6561
)
6662
}

crates/ide_db/src/helpers/insert_use.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ pub fn try_merge_imports(
213213
let lhs_tree = lhs.use_tree()?;
214214
let rhs_tree = rhs.use_tree()?;
215215
let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
216-
Some(lhs.with_use_tree(merged))
216+
Some(lhs.with_use_tree(merged).clone_for_update())
217217
}
218218

219219
pub fn try_merge_trees(
@@ -234,7 +234,7 @@ pub fn try_merge_trees(
234234
} else {
235235
(lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix))
236236
};
237-
recursive_merge(&lhs, &rhs, merge)
237+
recursive_merge(&lhs, &rhs, merge).map(|it| it.clone_for_update())
238238
}
239239

240240
/// Recursively "zips" together lhs and rhs.

crates/syntax/src/ast/edit.rs

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99
use arrayvec::ArrayVec;
1010

1111
use crate::{
12-
algo::{self, neighbor, SyntaxRewriter},
12+
algo::{self, SyntaxRewriter},
1313
ast::{
1414
self,
1515
make::{self, tokens},
@@ -322,27 +322,6 @@ impl ast::Use {
322322
}
323323
self.clone()
324324
}
325-
326-
pub fn remove(&self) -> SyntaxRewriter<'static> {
327-
let mut res = SyntaxRewriter::default();
328-
res.delete(self.syntax());
329-
let next_ws = self
330-
.syntax()
331-
.next_sibling_or_token()
332-
.and_then(|it| it.into_token())
333-
.and_then(ast::Whitespace::cast);
334-
if let Some(next_ws) = next_ws {
335-
let ws_text = next_ws.syntax().text();
336-
if let Some(rest) = ws_text.strip_prefix('\n') {
337-
if rest.is_empty() {
338-
res.delete(next_ws.syntax())
339-
} else {
340-
res.replace(next_ws.syntax(), &make::tokens::whitespace(rest));
341-
}
342-
}
343-
}
344-
res
345-
}
346325
}
347326

348327
impl ast::UseTree {
@@ -396,22 +375,6 @@ impl ast::UseTree {
396375
Some(res)
397376
}
398377
}
399-
400-
pub fn remove(&self) -> SyntaxRewriter<'static> {
401-
let mut res = SyntaxRewriter::default();
402-
res.delete(self.syntax());
403-
for &dir in [Direction::Next, Direction::Prev].iter() {
404-
if let Some(nb) = neighbor(self, dir) {
405-
self.syntax()
406-
.siblings_with_tokens(dir)
407-
.skip(1)
408-
.take_while(|it| it.as_node() != Some(nb.syntax()))
409-
.for_each(|el| res.delete(&el));
410-
return res;
411-
}
412-
}
413-
res
414-
}
415378
}
416379

417380
impl ast::MatchArmList {
@@ -592,6 +555,13 @@ impl ops::Add<u8> for IndentLevel {
592555
}
593556

594557
impl IndentLevel {
558+
pub fn from_element(element: &SyntaxElement) -> IndentLevel {
559+
match element {
560+
rowan::NodeOrToken::Node(it) => IndentLevel::from_node(it),
561+
rowan::NodeOrToken::Token(it) => IndentLevel::from_token(it),
562+
}
563+
}
564+
595565
pub fn from_node(node: &SyntaxNode) -> IndentLevel {
596566
match node.first_token() {
597567
Some(it) => Self::from_token(&it),

crates/syntax/src/ast/edit_in_place.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
33
use std::iter::empty;
44

5-
use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause};
65
use parser::T;
76

87
use crate::{
9-
ast,
8+
algo::neighbor,
9+
ast::{self, edit::AstNodeEdit, make, GenericParamsOwner, WhereClause},
1010
ted::{self, Position},
11-
AstNode, Direction,
11+
AstNode, AstToken, Direction,
1212
};
1313

1414
use super::NameOwner;
@@ -126,3 +126,41 @@ impl ast::TypeBoundList {
126126
}
127127
}
128128
}
129+
130+
impl ast::UseTree {
131+
pub fn remove(&self) {
132+
for &dir in [Direction::Next, Direction::Prev].iter() {
133+
if let Some(next_use_tree) = neighbor(self, dir) {
134+
let separators = self
135+
.syntax()
136+
.siblings_with_tokens(dir)
137+
.skip(1)
138+
.take_while(|it| it.as_node() != Some(next_use_tree.syntax()));
139+
ted::remove_all_iter(separators);
140+
break;
141+
}
142+
}
143+
ted::remove(self.syntax())
144+
}
145+
}
146+
147+
impl ast::Use {
148+
pub fn remove(&self) {
149+
let next_ws = self
150+
.syntax()
151+
.next_sibling_or_token()
152+
.and_then(|it| it.into_token())
153+
.and_then(ast::Whitespace::cast);
154+
if let Some(next_ws) = next_ws {
155+
let ws_text = next_ws.syntax().text();
156+
if let Some(rest) = ws_text.strip_prefix('\n') {
157+
if rest.is_empty() {
158+
ted::remove(next_ws.syntax())
159+
} else {
160+
ted::replace(next_ws.syntax(), make::tokens::whitespace(rest))
161+
}
162+
}
163+
}
164+
ted::remove(self.syntax())
165+
}
166+
}

crates/syntax/src/ast/make.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ pub mod tokens {
560560
pub fn whitespace(text: &str) -> SyntaxToken {
561561
assert!(text.trim().is_empty());
562562
let sf = SourceFile::parse(text).ok().unwrap();
563-
sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
563+
sf.syntax().clone_for_update().first_child_or_token().unwrap().into_token().unwrap()
564564
}
565565

566566
pub fn doc_comment(text: &str) -> SyntaxToken {

0 commit comments

Comments
 (0)