aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/diagnostics.rs21
-rw-r--r--crates/ide/src/diagnostics/field_shorthand.rs7
-rw-r--r--crates/ide/src/diagnostics/fixes.rs26
-rw-r--r--crates/ide/src/display/navigation_target.rs23
-rw-r--r--crates/ide/src/extend_selection.rs6
-rw-r--r--crates/ide/src/goto_definition.rs35
-rw-r--r--crates/ide/src/hover.rs47
-rw-r--r--crates/ide/src/join_lines.rs4
-rw-r--r--crates/ide/src/lib.rs6
-rw-r--r--crates/ide/src/references.rs119
-rw-r--r--crates/ide/src/references/rename.rs241
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs39
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html18
-rw-r--r--crates/ide/src/syntax_tree.rs4
-rw-r--r--crates/ide/src/typing.rs8
18 files changed, 255 insertions, 363 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 055c0a79c..b35bc2bae 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -13,17 +13,16 @@ use hir::{
13 diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, 13 diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder},
14 Semantics, 14 Semantics,
15}; 15};
16use ide_db::base_db::SourceDatabase; 16use ide_db::{base_db::SourceDatabase, RootDatabase};
17use ide_db::RootDatabase;
18use itertools::Itertools; 17use itertools::Itertools;
19use rustc_hash::FxHashSet; 18use rustc_hash::FxHashSet;
20use syntax::{ 19use syntax::{
21 ast::{self, AstNode}, 20 ast::{self, AstNode},
22 SyntaxNode, TextRange, T, 21 SyntaxNode, TextRange,
23}; 22};
24use text_edit::TextEdit; 23use text_edit::TextEdit;
25 24
26use crate::{FileId, Label, SourceChange, SourceFileEdit}; 25use crate::{FileId, Label, SourceChange};
27 26
28use self::fixes::DiagnosticWithFix; 27use self::fixes::DiagnosticWithFix;
29 28
@@ -220,7 +219,7 @@ fn check_unnecessary_braces_in_use_statement(
220 Diagnostic::hint(use_range, "Unnecessary braces in use statement".to_string()) 219 Diagnostic::hint(use_range, "Unnecessary braces in use statement".to_string())
221 .with_fix(Some(Fix::new( 220 .with_fix(Some(Fix::new(
222 "Remove unnecessary braces", 221 "Remove unnecessary braces",
223 SourceFileEdit { file_id, edit }.into(), 222 SourceChange::from_text_edit(file_id, edit),
224 use_range, 223 use_range,
225 ))), 224 ))),
226 ); 225 );
@@ -233,7 +232,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
233 single_use_tree: &ast::UseTree, 232 single_use_tree: &ast::UseTree,
234) -> Option<TextEdit> { 233) -> Option<TextEdit> {
235 let use_tree_list_node = single_use_tree.syntax().parent()?; 234 let use_tree_list_node = single_use_tree.syntax().parent()?;
236 if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] { 235 if single_use_tree.path()?.segment()?.self_token().is_some() {
237 let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start(); 236 let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start();
238 let end = use_tree_list_node.text_range().end(); 237 let end = use_tree_list_node.text_range().end();
239 return Some(TextEdit::delete(TextRange::new(start, end))); 238 return Some(TextEdit::delete(TextRange::new(start, end)));
@@ -265,13 +264,11 @@ mod tests {
265 .unwrap(); 264 .unwrap();
266 let fix = diagnostic.fix.unwrap(); 265 let fix = diagnostic.fix.unwrap();
267 let actual = { 266 let actual = {
268 let file_id = fix.source_change.source_file_edits.first().unwrap().file_id; 267 let file_id = *fix.source_change.source_file_edits.keys().next().unwrap();
269 let mut actual = analysis.file_text(file_id).unwrap().to_string(); 268 let mut actual = analysis.file_text(file_id).unwrap().to_string();
270 269
271 // Go from the last one to the first one, so that ranges won't be affected by previous edits. 270 for edit in fix.source_change.source_file_edits.values() {
272 // FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/4901#issuecomment-644675309 271 edit.apply(&mut actual);
273 for edit in fix.source_change.source_file_edits.iter().rev() {
274 edit.edit.apply(&mut actual);
275 } 272 }
276 actual 273 actual
277 }; 274 };
@@ -616,7 +613,7 @@ fn test_fn() {
616 Fix { 613 Fix {
617 label: "Create module", 614 label: "Create module",
618 source_change: SourceChange { 615 source_change: SourceChange {
619 source_file_edits: [], 616 source_file_edits: {},
620 file_system_edits: [ 617 file_system_edits: [
621 CreateFile { 618 CreateFile {
622 dst: AnchoredPathBuf { 619 dst: AnchoredPathBuf {
diff --git a/crates/ide/src/diagnostics/field_shorthand.rs b/crates/ide/src/diagnostics/field_shorthand.rs
index 16c6ea827..5c89e2170 100644
--- a/crates/ide/src/diagnostics/field_shorthand.rs
+++ b/crates/ide/src/diagnostics/field_shorthand.rs
@@ -1,8 +1,7 @@
1//! Suggests shortening `Foo { field: field }` to `Foo { field }` in both 1//! Suggests shortening `Foo { field: field }` to `Foo { field }` in both
2//! expressions and patterns. 2//! expressions and patterns.
3 3
4use ide_db::base_db::FileId; 4use ide_db::{base_db::FileId, source_change::SourceChange};
5use ide_db::source_change::SourceFileEdit;
6use syntax::{ast, match_ast, AstNode, SyntaxNode}; 5use syntax::{ast, match_ast, AstNode, SyntaxNode};
7use text_edit::TextEdit; 6use text_edit::TextEdit;
8 7
@@ -50,7 +49,7 @@ fn check_expr_field_shorthand(
50 Diagnostic::hint(field_range, "Shorthand struct initialization".to_string()).with_fix( 49 Diagnostic::hint(field_range, "Shorthand struct initialization".to_string()).with_fix(
51 Some(Fix::new( 50 Some(Fix::new(
52 "Use struct shorthand initialization", 51 "Use struct shorthand initialization",
53 SourceFileEdit { file_id, edit }.into(), 52 SourceChange::from_text_edit(file_id, edit),
54 field_range, 53 field_range,
55 )), 54 )),
56 ), 55 ),
@@ -89,7 +88,7 @@ fn check_pat_field_shorthand(
89 acc.push(Diagnostic::hint(field_range, "Shorthand struct pattern".to_string()).with_fix( 88 acc.push(Diagnostic::hint(field_range, "Shorthand struct pattern".to_string()).with_fix(
90 Some(Fix::new( 89 Some(Fix::new(
91 "Use struct field shorthand", 90 "Use struct field shorthand",
92 SourceFileEdit { file_id, edit }.into(), 91 SourceChange::from_text_edit(file_id, edit),
93 field_range, 92 field_range,
94 )), 93 )),
95 )); 94 ));
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index d7ad88ed5..e4335119b 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -8,9 +8,9 @@ use hir::{
8 }, 8 },
9 HasSource, HirDisplay, InFile, Semantics, VariantDef, 9 HasSource, HirDisplay, InFile, Semantics, VariantDef,
10}; 10};
11use ide_db::base_db::{AnchoredPathBuf, FileId};
12use ide_db::{ 11use ide_db::{
13 source_change::{FileSystemEdit, SourceFileEdit}, 12 base_db::{AnchoredPathBuf, FileId},
13 source_change::{FileSystemEdit, SourceChange},
14 RootDatabase, 14 RootDatabase,
15}; 15};
16use syntax::{ 16use syntax::{
@@ -88,7 +88,7 @@ impl DiagnosticWithFix for MissingFields {
88 }; 88 };
89 Some(Fix::new( 89 Some(Fix::new(
90 "Fill struct fields", 90 "Fill struct fields",
91 SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(), 91 SourceChange::from_text_edit(self.file.original_file(sema.db), edit),
92 sema.original_range(&field_list_parent.syntax()).range, 92 sema.original_range(&field_list_parent.syntax()).range,
93 )) 93 ))
94 } 94 }
@@ -101,8 +101,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
101 let tail_expr_range = tail_expr.syntax().text_range(); 101 let tail_expr_range = tail_expr.syntax().text_range();
102 let replacement = format!("{}({})", self.required, tail_expr.syntax()); 102 let replacement = format!("{}({})", self.required, tail_expr.syntax());
103 let edit = TextEdit::replace(tail_expr_range, replacement); 103 let edit = TextEdit::replace(tail_expr_range, replacement);
104 let source_change = 104 let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
105 SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();
106 let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" }; 105 let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" };
107 Some(Fix::new(name, source_change, tail_expr_range)) 106 Some(Fix::new(name, source_change, tail_expr_range))
108 } 107 }
@@ -122,8 +121,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon {
122 .text_range(); 121 .text_range();
123 122
124 let edit = TextEdit::delete(semicolon); 123 let edit = TextEdit::delete(semicolon);
125 let source_change = 124 let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
126 SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();
127 125
128 Some(Fix::new("Remove this semicolon", source_change, semicolon)) 126 Some(Fix::new("Remove this semicolon", source_change, semicolon))
129 } 127 }
@@ -204,15 +202,11 @@ fn missing_record_expr_field_fix(
204 new_field = format!(",{}", new_field); 202 new_field = format!(",{}", new_field);
205 } 203 }
206 204
207 let source_change = SourceFileEdit { 205 let source_change = SourceChange::from_text_edit(
208 file_id: def_file_id, 206 def_file_id,
209 edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field), 207 TextEdit::insert(last_field_syntax.text_range().end(), new_field),
210 }; 208 );
211 return Some(Fix::new( 209 return Some(Fix::new("Create field", source_change, record_expr_field.syntax().text_range()));
212 "Create field",
213 source_change.into(),
214 record_expr_field.syntax().text_range(),
215 ));
216 210
217 fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> { 211 fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> {
218 match field_def_list { 212 match field_def_list {
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 4eecae697..685052e7f 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -400,24 +400,33 @@ impl TryToNav for hir::GenericParam {
400impl ToNav for hir::Local { 400impl ToNav for hir::Local {
401 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 401 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
402 let src = self.source(db); 402 let src = self.source(db);
403 let node = match &src.value { 403 let (node, focus_range) = match &src.value {
404 Either::Left(bind_pat) => { 404 Either::Left(bind_pat) => (
405 bind_pat.name().map_or_else(|| bind_pat.syntax().clone(), |it| it.syntax().clone()) 405 bind_pat.syntax().clone(),
406 } 406 bind_pat
407 Either::Right(it) => it.syntax().clone(), 407 .name()
408 .map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range),
409 ),
410 Either::Right(it) => (it.syntax().clone(), it.self_token().map(|it| it.text_range())),
408 }; 411 };
409 let full_range = src.with_value(&node).original_file_range(db); 412 let full_range = src.with_value(&node).original_file_range(db);
410 let name = match self.name(db) { 413 let name = match self.name(db) {
411 Some(it) => it.to_string().into(), 414 Some(it) => it.to_string().into(),
412 None => "".into(), 415 None => "".into(),
413 }; 416 };
414 let kind = if self.is_param(db) { SymbolKind::ValueParam } else { SymbolKind::Local }; 417 let kind = if self.is_self(db) {
418 SymbolKind::SelfParam
419 } else if self.is_param(db) {
420 SymbolKind::ValueParam
421 } else {
422 SymbolKind::Local
423 };
415 NavigationTarget { 424 NavigationTarget {
416 file_id: full_range.file_id, 425 file_id: full_range.file_id,
417 name, 426 name,
418 kind: Some(kind), 427 kind: Some(kind),
419 full_range: full_range.range, 428 full_range: full_range.range,
420 focus_range: None, 429 focus_range,
421 container_name: None, 430 container_name: None,
422 description: None, 431 description: None,
423 docs: None, 432 docs: None,
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs
index 56418c960..17a540972 100644
--- a/crates/ide/src/extend_selection.rs
+++ b/crates/ide/src/extend_selection.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use syntax::{ 5use syntax::{
6 algo::{self, find_covering_element, skip_trivia_token}, 6 algo::{self, skip_trivia_token},
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8 Direction, NodeOrToken, 8 Direction, NodeOrToken,
9 SyntaxKind::{self, *}, 9 SyntaxKind::{self, *},
@@ -76,7 +76,7 @@ fn try_extend_selection(
76 }; 76 };
77 return Some(leaf_range); 77 return Some(leaf_range);
78 }; 78 };
79 let node = match find_covering_element(root, range) { 79 let node = match root.covering_element(range) {
80 NodeOrToken::Token(token) => { 80 NodeOrToken::Token(token) => {
81 if token.text_range() != range { 81 if token.text_range() != range {
82 return Some(token.text_range()); 82 return Some(token.text_range());
@@ -120,7 +120,7 @@ fn extend_tokens_from_range(
120 macro_call: ast::MacroCall, 120 macro_call: ast::MacroCall,
121 original_range: TextRange, 121 original_range: TextRange,
122) -> Option<TextRange> { 122) -> Option<TextRange> {
123 let src = find_covering_element(&macro_call.syntax(), original_range); 123 let src = macro_call.syntax().covering_element(original_range);
124 let (first_token, last_token) = match src { 124 let (first_token, last_token) = match src {
125 NodeOrToken::Node(it) => (it.first_token()?, it.last_token()?), 125 NodeOrToken::Node(it) => (it.first_token()?, it.last_token()?),
126 NodeOrToken::Token(it) => (it.clone(), it), 126 NodeOrToken::Token(it) => (it.clone(), it),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index cd4afc804..988a5668f 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1,7 +1,6 @@
1use either::Either; 1use either::Either;
2use hir::{HasAttrs, ModuleDef, Semantics}; 2use hir::{HasAttrs, ModuleDef, Semantics};
3use ide_db::{ 3use ide_db::{
4 base_db::FileId,
5 defs::{Definition, NameClass, NameRefClass}, 4 defs::{Definition, NameClass, NameRefClass},
6 symbol_index, RootDatabase, 5 symbol_index, RootDatabase,
7}; 6};
@@ -13,7 +12,7 @@ use crate::{
13 display::{ToNav, TryToNav}, 12 display::{ToNav, TryToNav},
14 doc_links::extract_definitions_from_markdown, 13 doc_links::extract_definitions_from_markdown,
15 runnables::doc_owner_to_def, 14 runnables::doc_owner_to_def,
16 FilePosition, NavigationTarget, RangeInfo, SymbolKind, 15 FilePosition, NavigationTarget, RangeInfo,
17}; 16};
18 17
19// Feature: Go to Definition 18// Feature: Go to Definition
@@ -49,19 +48,6 @@ pub(crate) fn goto_definition(
49 let nav = def.try_to_nav(sema.db)?; 48 let nav = def.try_to_nav(sema.db)?;
50 vec![nav] 49 vec![nav]
51 }, 50 },
52 ast::SelfParam(self_param) => {
53 vec![self_to_nav_target(self_param, position.file_id)?]
54 },
55 ast::PathSegment(segment) => {
56 segment.self_token()?;
57 let path = segment.parent_path();
58 if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
59 return None;
60 }
61 let func = segment.syntax().ancestors().find_map(ast::Fn::cast)?;
62 let self_param = func.param_list()?.self_param()?;
63 vec![self_to_nav_target(self_param, position.file_id)?]
64 },
65 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) { 51 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
66 let def = name_class.referenced_or_defined(sema.db); 52 let def = name_class.referenced_or_defined(sema.db);
67 let nav = def.try_to_nav(sema.db)?; 53 let nav = def.try_to_nav(sema.db)?;
@@ -69,6 +55,11 @@ pub(crate) fn goto_definition(
69 } else { 55 } else {
70 reference_definition(&sema, Either::Left(&lt)).to_vec() 56 reference_definition(&sema, Either::Left(&lt)).to_vec()
71 }, 57 },
58 ast::SelfParam(self_param) => {
59 let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db);
60 let nav = def.try_to_nav(sema.db)?;
61 vec![nav]
62 },
72 _ => return None, 63 _ => return None,
73 } 64 }
74 }; 65 };
@@ -134,20 +125,6 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
134 } 125 }
135} 126}
136 127
137fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<NavigationTarget> {
138 let self_token = self_param.self_token()?;
139 Some(NavigationTarget {
140 file_id,
141 full_range: self_param.syntax().text_range(),
142 focus_range: Some(self_token.text_range()),
143 name: self_token.text().clone(),
144 kind: Some(SymbolKind::SelfParam),
145 container_name: None,
146 description: None,
147 docs: None,
148 })
149}
150
151#[derive(Debug)] 128#[derive(Debug)]
152pub(crate) enum ReferenceResult { 129pub(crate) enum ReferenceResult {
153 Exact(NavigationTarget), 130 Exact(NavigationTarget),
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 317b6f011..6022bd275 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -98,6 +98,7 @@ pub(crate) fn hover(
98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), 98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) 99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), 100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
101 ast::SelfParam(self_param) => NameClass::classify_self_param(&sema, &self_param).and_then(|d| d.defined(sema.db)),
101 _ => None, 102 _ => None,
102 } 103 }
103 }; 104 };
@@ -134,17 +135,14 @@ pub(crate) fn hover(
134 return None; 135 return None;
135 } 136 }
136 137
137 let node = token.ancestors().find(|n| { 138 let node = token
138 ast::Expr::can_cast(n.kind()) 139 .ancestors()
139 || ast::Pat::can_cast(n.kind()) 140 .find(|n| ast::Expr::can_cast(n.kind()) || ast::Pat::can_cast(n.kind()))?;
140 || ast::SelfParam::can_cast(n.kind())
141 })?;
142 141
143 let ty = match_ast! { 142 let ty = match_ast! {
144 match node { 143 match node {
145 ast::Expr(it) => sema.type_of_expr(&it)?, 144 ast::Expr(it) => sema.type_of_expr(&it)?,
146 ast::Pat(it) => sema.type_of_pat(&it)?, 145 ast::Pat(it) => sema.type_of_pat(&it)?,
147 ast::SelfParam(self_param) => sema.type_of_self(&self_param)?,
148 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. 146 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
149 // (e.g expanding a builtin macro). So we give up here. 147 // (e.g expanding a builtin macro). So we give up here.
150 ast::MacroCall(_it) => return None, 148 ast::MacroCall(_it) => return None,
@@ -386,7 +384,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
386 return tokens.max_by_key(priority); 384 return tokens.max_by_key(priority);
387 fn priority(n: &SyntaxToken) -> usize { 385 fn priority(n: &SyntaxToken) -> usize {
388 match n.kind() { 386 match n.kind() {
389 IDENT | INT_NUMBER | LIFETIME_IDENT => 3, 387 IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] => 3,
390 T!['('] | T![')'] => 2, 388 T!['('] | T![')'] => 2,
391 kind if kind.is_trivia() => 0, 389 kind if kind.is_trivia() => 0,
392 _ => 1, 390 _ => 1,
@@ -3130,6 +3128,39 @@ fn foo<T: Foo>(t: T$0){}
3130 } 3128 }
3131 3129
3132 #[test] 3130 #[test]
3131 fn test_hover_self_has_go_to_type() {
3132 check_actions(
3133 r#"
3134struct Foo;
3135impl Foo {
3136 fn foo(&self$0) {}
3137}
3138"#,
3139 expect![[r#"
3140 [
3141 GoToType(
3142 [
3143 HoverGotoTypeData {
3144 mod_path: "test::Foo",
3145 nav: NavigationTarget {
3146 file_id: FileId(
3147 0,
3148 ),
3149 full_range: 0..11,
3150 focus_range: 7..10,
3151 name: "Foo",
3152 kind: Struct,
3153 description: "struct Foo",
3154 },
3155 },
3156 ],
3157 ),
3158 ]
3159 "#]],
3160 );
3161 }
3162
3163 #[test]
3133 fn hover_displays_normalized_crate_names() { 3164 fn hover_displays_normalized_crate_names() {
3134 check( 3165 check(
3135 r#" 3166 r#"
@@ -3193,6 +3224,7 @@ impl Foo {
3193"#, 3224"#,
3194 expect![[r#" 3225 expect![[r#"
3195 *&self* 3226 *&self*
3227
3196 ```rust 3228 ```rust
3197 &Foo 3229 &Foo
3198 ``` 3230 ```
@@ -3212,6 +3244,7 @@ impl Foo {
3212"#, 3244"#,
3213 expect![[r#" 3245 expect![[r#"
3214 *self: Arc<Foo>* 3246 *self: Arc<Foo>*
3247
3215 ```rust 3248 ```rust
3216 Arc<Foo> 3249 Arc<Foo>
3217 ``` 3250 ```
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs
index 05380f2a1..981467c8d 100644
--- a/crates/ide/src/join_lines.rs
+++ b/crates/ide/src/join_lines.rs
@@ -1,7 +1,7 @@
1use assists::utils::extract_trivial_expression; 1use assists::utils::extract_trivial_expression;
2use itertools::Itertools; 2use itertools::Itertools;
3use syntax::{ 3use syntax::{
4 algo::{find_covering_element, non_trivia_sibling}, 4 algo::non_trivia_sibling,
5 ast::{self, AstNode, AstToken}, 5 ast::{self, AstNode, AstToken},
6 Direction, NodeOrToken, SourceFile, 6 Direction, NodeOrToken, SourceFile,
7 SyntaxKind::{self, USE_TREE, WHITESPACE}, 7 SyntaxKind::{self, USE_TREE, WHITESPACE},
@@ -31,7 +31,7 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
31 range 31 range
32 }; 32 };
33 33
34 let node = match find_covering_element(file.syntax(), range) { 34 let node = match file.syntax().covering_element(range) {
35 NodeOrToken::Node(node) => node, 35 NodeOrToken::Node(node) => node,
36 NodeOrToken::Token(token) => token.parent(), 36 NodeOrToken::Token(token) => token.parent(),
37 }; 37 };
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 1e03832ec..f8d69382e 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -80,7 +80,7 @@ pub use crate::{
80 HlRange, 80 HlRange,
81 }, 81 },
82}; 82};
83pub use assists::{Assist, AssistConfig, AssistId, AssistKind, InsertUseConfig}; 83pub use assists::{Assist, AssistConfig, AssistId, AssistKind};
84pub use completion::{ 84pub use completion::{
85 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, 85 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit,
86 InsertTextFormat, 86 InsertTextFormat,
@@ -98,7 +98,7 @@ pub use ide_db::{
98 label::Label, 98 label::Label,
99 line_index::{LineCol, LineIndex}, 99 line_index::{LineCol, LineIndex},
100 search::SearchScope, 100 search::SearchScope,
101 source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, 101 source_change::{FileSystemEdit, SourceChange},
102 symbol_index::Query, 102 symbol_index::Query,
103 RootDatabase, 103 RootDatabase,
104}; 104};
@@ -553,7 +553,7 @@ impl Analysis {
553 let rule: ssr::SsrRule = query.parse()?; 553 let rule: ssr::SsrRule = query.parse()?;
554 let mut match_finder = ssr::MatchFinder::in_context(db, resolve_context, selections); 554 let mut match_finder = ssr::MatchFinder::in_context(db, resolve_context, selections);
555 match_finder.add_rule(rule)?; 555 match_finder.add_rule(rule)?;
556 let edits = if parse_only { Vec::new() } else { match_finder.edits() }; 556 let edits = if parse_only { Default::default() } else { match_finder.edits() };
557 Ok(SourceChange::from(edits)) 557 Ok(SourceChange::from(edits))
558 }) 558 })
559 } 559 }
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 7d4757e02..51a2f4327 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -11,6 +11,7 @@
11 11
12pub(crate) mod rename; 12pub(crate) mod rename;
13 13
14use either::Either;
14use hir::Semantics; 15use hir::Semantics;
15use ide_db::{ 16use ide_db::{
16 base_db::FileId, 17 base_db::FileId,
@@ -21,10 +22,10 @@ use ide_db::{
21use syntax::{ 22use syntax::{
22 algo::find_node_at_offset, 23 algo::find_node_at_offset,
23 ast::{self, NameOwner}, 24 ast::{self, NameOwner},
24 match_ast, AstNode, SyntaxNode, TextRange, TokenAtOffset, T, 25 AstNode, SyntaxNode, TextRange, TokenAtOffset, T,
25}; 26};
26 27
27use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; 28use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
28 29
29#[derive(Debug, Clone)] 30#[derive(Debug, Clone)]
30pub struct ReferenceSearchResult { 31pub struct ReferenceSearchResult {
@@ -90,10 +91,6 @@ pub(crate) fn find_all_refs(
90 let _p = profile::span("find_all_refs"); 91 let _p = profile::span("find_all_refs");
91 let syntax = sema.parse(position.file_id).syntax().clone(); 92 let syntax = sema.parse(position.file_id).syntax().clone();
92 93
93 if let Some(res) = try_find_self_references(&syntax, position) {
94 return Some(res);
95 }
96
97 let (opt_name, search_kind) = if let Some(name) = 94 let (opt_name, search_kind) = if let Some(name) =
98 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) 95 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
99 { 96 {
@@ -122,13 +119,16 @@ pub(crate) fn find_all_refs(
122 119
123 let mut kind = ReferenceKind::Other; 120 let mut kind = ReferenceKind::Other;
124 if let Definition::Local(local) = def { 121 if let Definition::Local(local) = def {
125 if let either::Either::Left(pat) = local.source(sema.db).value { 122 match local.source(sema.db).value {
126 if matches!( 123 Either::Left(pat) => {
127 pat.syntax().parent().and_then(ast::RecordPatField::cast), 124 if matches!(
128 Some(pat_field) if pat_field.name_ref().is_none() 125 pat.syntax().parent().and_then(ast::RecordPatField::cast),
129 ) { 126 Some(pat_field) if pat_field.name_ref().is_none()
130 kind = ReferenceKind::FieldShorthandForLocal; 127 ) {
128 kind = ReferenceKind::FieldShorthandForLocal;
129 }
131 } 130 }
131 Either::Right(_) => kind = ReferenceKind::SelfParam,
132 } 132 }
133 } else if matches!( 133 } else if matches!(
134 def, 134 def,
@@ -251,79 +251,6 @@ fn get_enum_def_name_for_struct_literal_search(
251 None 251 None
252} 252}
253 253
254fn try_find_self_references(
255 syntax: &SyntaxNode,
256 position: FilePosition,
257) -> Option<RangeInfo<ReferenceSearchResult>> {
258 let FilePosition { file_id, offset } = position;
259 let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?;
260 let parent = self_token.parent();
261 match_ast! {
262 match parent {
263 ast::SelfParam(it) => (),
264 ast::PathSegment(segment) => {
265 segment.self_token()?;
266 let path = segment.parent_path();
267 if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
268 return None;
269 }
270 },
271 _ => return None,
272 }
273 };
274 let function = parent.ancestors().find_map(ast::Fn::cast)?;
275 let self_param = function.param_list()?.self_param()?;
276 let param_self_token = self_param.self_token()?;
277
278 let declaration = Declaration {
279 nav: NavigationTarget {
280 file_id,
281 full_range: self_param.syntax().text_range(),
282 focus_range: Some(param_self_token.text_range()),
283 name: param_self_token.text().clone(),
284 kind: Some(SymbolKind::SelfParam),
285 container_name: None,
286 description: None,
287 docs: None,
288 },
289 kind: ReferenceKind::SelfKw,
290 access: Some(if self_param.mut_token().is_some() {
291 ReferenceAccess::Write
292 } else {
293 ReferenceAccess::Read
294 }),
295 };
296 let refs = function
297 .body()
298 .map(|body| {
299 body.syntax()
300 .descendants()
301 .filter_map(ast::PathExpr::cast)
302 .filter_map(|expr| {
303 let path = expr.path()?;
304 if path.qualifier().is_none() {
305 path.segment()?.self_token()
306 } else {
307 None
308 }
309 })
310 .map(|token| FileReference {
311 range: token.text_range(),
312 kind: ReferenceKind::SelfKw,
313 access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration
314 })
315 .collect()
316 })
317 .unwrap_or_default();
318 let mut references = UsageSearchResult::default();
319 references.references.insert(file_id, refs);
320
321 Some(RangeInfo::new(
322 param_self_token.text_range(),
323 ReferenceSearchResult { declaration, references },
324 ))
325}
326
327#[cfg(test)] 254#[cfg(test)]
328mod tests { 255mod tests {
329 use expect_test::{expect, Expect}; 256 use expect_test::{expect, Expect};
@@ -512,7 +439,7 @@ fn main() {
512 i = 5; 439 i = 5;
513}"#, 440}"#,
514 expect![[r#" 441 expect![[r#"
515 i Local FileId(0) 24..25 Other Write 442 i Local FileId(0) 20..25 24..25 Other Write
516 443
517 FileId(0) 50..51 Other Write 444 FileId(0) 50..51 Other Write
518 FileId(0) 54..55 Other Read 445 FileId(0) 54..55 Other Read
@@ -536,7 +463,7 @@ fn bar() {
536} 463}
537"#, 464"#,
538 expect![[r#" 465 expect![[r#"
539 spam Local FileId(0) 19..23 Other 466 spam Local FileId(0) 19..23 19..23 Other
540 467
541 FileId(0) 34..38 Other Read 468 FileId(0) 34..38 Other Read
542 FileId(0) 41..45 Other Read 469 FileId(0) 41..45 Other Read
@@ -551,7 +478,7 @@ fn bar() {
551fn foo(i : u32) -> u32 { i$0 } 478fn foo(i : u32) -> u32 { i$0 }
552"#, 479"#,
553 expect![[r#" 480 expect![[r#"
554 i ValueParam FileId(0) 7..8 Other 481 i ValueParam FileId(0) 7..8 7..8 Other
555 482
556 FileId(0) 25..26 Other Read 483 FileId(0) 25..26 Other Read
557 "#]], 484 "#]],
@@ -565,7 +492,7 @@ fn foo(i : u32) -> u32 { i$0 }
565fn foo(i$0 : u32) -> u32 { i } 492fn foo(i$0 : u32) -> u32 { i }
566"#, 493"#,
567 expect![[r#" 494 expect![[r#"
568 i ValueParam FileId(0) 7..8 Other 495 i ValueParam FileId(0) 7..8 7..8 Other
569 496
570 FileId(0) 25..26 Other Read 497 FileId(0) 25..26 Other Read
571 "#]], 498 "#]],
@@ -813,7 +740,7 @@ fn foo() {
813} 740}
814"#, 741"#,
815 expect![[r#" 742 expect![[r#"
816 i Local FileId(0) 23..24 Other Write 743 i Local FileId(0) 19..24 23..24 Other Write
817 744
818 FileId(0) 34..35 Other Write 745 FileId(0) 34..35 Other Write
819 FileId(0) 38..39 Other Read 746 FileId(0) 38..39 Other Read
@@ -853,7 +780,7 @@ fn foo() {
853} 780}
854"#, 781"#,
855 expect![[r#" 782 expect![[r#"
856 i Local FileId(0) 19..20 Other 783 i Local FileId(0) 19..20 19..20 Other
857 784
858 FileId(0) 26..27 Other Write 785 FileId(0) 26..27 Other Write
859 "#]], 786 "#]],
@@ -995,10 +922,10 @@ impl Foo {
995} 922}
996"#, 923"#,
997 expect![[r#" 924 expect![[r#"
998 self SelfParam FileId(0) 47..51 47..51 SelfKw Read 925 self SelfParam FileId(0) 47..51 47..51 SelfParam
999 926
1000 FileId(0) 71..75 SelfKw Read 927 FileId(0) 71..75 Other Read
1001 FileId(0) 152..156 SelfKw Read 928 FileId(0) 152..156 Other Read
1002 "#]], 929 "#]],
1003 ); 930 );
1004 } 931 }
@@ -1105,7 +1032,7 @@ fn main() {
1105} 1032}
1106"#, 1033"#,
1107 expect![[r#" 1034 expect![[r#"
1108 a Local FileId(0) 59..60 Other 1035 a Local FileId(0) 59..60 59..60 Other
1109 1036
1110 FileId(0) 80..81 Other Read 1037 FileId(0) 80..81 Other Read
1111 "#]], 1038 "#]],
@@ -1123,7 +1050,7 @@ fn main() {
1123} 1050}
1124"#, 1051"#,
1125 expect![[r#" 1052 expect![[r#"
1126 a Local FileId(0) 59..60 Other 1053 a Local FileId(0) 59..60 59..60 Other
1127 1054
1128 FileId(0) 80..81 Other Read 1055 FileId(0) 80..81 Other Read
1129 "#]], 1056 "#]],
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index c3ae568c2..9ac4af026 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -21,7 +21,7 @@ use text_edit::TextEdit;
21 21
22use crate::{ 22use crate::{
23 FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange, 23 FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange,
24 SourceFileEdit, TextRange, TextSize, 24 TextRange, TextSize,
25}; 25};
26 26
27type RenameResult<T> = Result<T, RenameError>; 27type RenameResult<T> = Result<T, RenameError>;
@@ -58,7 +58,7 @@ pub(crate) fn prepare_rename(
58 rename_self_to_param(&sema, position, self_token, "dummy") 58 rename_self_to_param(&sema, position, self_token, "dummy")
59 } else { 59 } else {
60 let RangeInfo { range, .. } = find_all_refs(&sema, position)?; 60 let RangeInfo { range, .. } = find_all_refs(&sema, position)?;
61 Ok(RangeInfo::new(range, SourceChange::from(vec![]))) 61 Ok(RangeInfo::new(range, SourceChange::default()))
62 } 62 }
63 .map(|info| RangeInfo::new(info.range, ())) 63 .map(|info| RangeInfo::new(info.range, ()))
64} 64}
@@ -176,7 +176,7 @@ fn source_edit_from_references(
176 file_id: FileId, 176 file_id: FileId,
177 references: &[FileReference], 177 references: &[FileReference],
178 new_name: &str, 178 new_name: &str,
179) -> SourceFileEdit { 179) -> (FileId, TextEdit) {
180 let mut edit = TextEdit::builder(); 180 let mut edit = TextEdit::builder();
181 for reference in references { 181 for reference in references {
182 let mut replacement_text = String::new(); 182 let mut replacement_text = String::new();
@@ -209,8 +209,7 @@ fn source_edit_from_references(
209 }; 209 };
210 edit.replace(range, replacement_text); 210 edit.replace(range, replacement_text);
211 } 211 }
212 212 (file_id, edit.finish())
213 SourceFileEdit { file_id, edit: edit.finish() }
214} 213}
215 214
216fn edit_text_range_for_record_field_expr_or_pat( 215fn edit_text_range_for_record_field_expr_or_pat(
@@ -250,8 +249,8 @@ fn rename_mod(
250 if IdentifierKind::Ident != check_identifier(new_name)? { 249 if IdentifierKind::Ident != check_identifier(new_name)? {
251 bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); 250 bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
252 } 251 }
253 let mut source_file_edits = Vec::new(); 252
254 let mut file_system_edits = Vec::new(); 253 let mut source_change = SourceChange::default();
255 254
256 let src = module.definition_source(sema.db); 255 let src = module.definition_source(sema.db);
257 let file_id = src.file_id.original_file(sema.db); 256 let file_id = src.file_id.original_file(sema.db);
@@ -265,7 +264,7 @@ fn rename_mod(
265 }; 264 };
266 let dst = AnchoredPathBuf { anchor: file_id, path }; 265 let dst = AnchoredPathBuf { anchor: file_id, path };
267 let move_file = FileSystemEdit::MoveFile { src: file_id, dst }; 266 let move_file = FileSystemEdit::MoveFile { src: file_id, dst };
268 file_system_edits.push(move_file); 267 source_change.push_file_system_edit(move_file);
269 } 268 }
270 ModuleSource::Module(..) => {} 269 ModuleSource::Module(..) => {}
271 } 270 }
@@ -273,20 +272,19 @@ fn rename_mod(
273 if let Some(src) = module.declaration_source(sema.db) { 272 if let Some(src) = module.declaration_source(sema.db) {
274 let file_id = src.file_id.original_file(sema.db); 273 let file_id = src.file_id.original_file(sema.db);
275 let name = src.value.name().unwrap(); 274 let name = src.value.name().unwrap();
276 let edit = SourceFileEdit { 275 source_change.insert_source_edit(
277 file_id, 276 file_id,
278 edit: TextEdit::replace(name.syntax().text_range(), new_name.into()), 277 TextEdit::replace(name.syntax().text_range(), new_name.into()),
279 }; 278 );
280 source_file_edits.push(edit);
281 } 279 }
282 280
283 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; 281 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
284 let ref_edits = refs.references().iter().map(|(&file_id, references)| { 282 let ref_edits = refs.references().iter().map(|(&file_id, references)| {
285 source_edit_from_references(sema, file_id, references, new_name) 283 source_edit_from_references(sema, file_id, references, new_name)
286 }); 284 });
287 source_file_edits.extend(ref_edits); 285 source_change.extend(ref_edits);
288 286
289 Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) 287 Ok(RangeInfo::new(range, source_change))
290} 288}
291 289
292fn rename_to_self( 290fn rename_to_self(
@@ -335,20 +333,16 @@ fn rename_to_self(
335 333
336 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; 334 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
337 335
338 let mut edits = refs 336 let mut source_change = SourceChange::default();
339 .references() 337 source_change.extend(refs.references().iter().map(|(&file_id, references)| {
340 .iter() 338 source_edit_from_references(sema, file_id, references, "self")
341 .map(|(&file_id, references)| { 339 }));
342 source_edit_from_references(sema, file_id, references, "self") 340 source_change.insert_source_edit(
343 }) 341 position.file_id,
344 .collect::<Vec<_>>(); 342 TextEdit::replace(param_range, String::from(self_param)),
345 343 );
346 edits.push(SourceFileEdit {
347 file_id: position.file_id,
348 edit: TextEdit::replace(param_range, String::from(self_param)),
349 });
350 344
351 Ok(RangeInfo::new(range, SourceChange::from(edits))) 345 Ok(RangeInfo::new(range, source_change))
352} 346}
353 347
354fn text_edit_from_self_param( 348fn text_edit_from_self_param(
@@ -402,7 +396,7 @@ fn rename_self_to_param(
402 .ok_or_else(|| format_err!("No surrounding method declaration found"))?; 396 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
403 let search_range = fn_def.syntax().text_range(); 397 let search_range = fn_def.syntax().text_range();
404 398
405 let mut edits: Vec<SourceFileEdit> = vec![]; 399 let mut source_change = SourceChange::default();
406 400
407 for (idx, _) in text.match_indices("self") { 401 for (idx, _) in text.match_indices("self") {
408 let offset: TextSize = idx.try_into().unwrap(); 402 let offset: TextSize = idx.try_into().unwrap();
@@ -416,18 +410,18 @@ fn rename_self_to_param(
416 } else { 410 } else {
417 TextEdit::replace(usage.text_range(), String::from(new_name)) 411 TextEdit::replace(usage.text_range(), String::from(new_name))
418 }; 412 };
419 edits.push(SourceFileEdit { file_id: position.file_id, edit }); 413 source_change.insert_source_edit(position.file_id, edit);
420 } 414 }
421 } 415 }
422 416
423 if edits.len() > 1 && ident_kind == IdentifierKind::Underscore { 417 if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore {
424 bail!("Cannot rename reference to `_` as it is being referenced multiple times"); 418 bail!("Cannot rename reference to `_` as it is being referenced multiple times");
425 } 419 }
426 420
427 let range = ast::SelfParam::cast(self_token.parent()) 421 let range = ast::SelfParam::cast(self_token.parent())
428 .map_or(self_token.text_range(), |p| p.syntax().text_range()); 422 .map_or(self_token.text_range(), |p| p.syntax().text_range());
429 423
430 Ok(RangeInfo::new(range, SourceChange::from(edits))) 424 Ok(RangeInfo::new(range, source_change))
431} 425}
432 426
433fn rename_reference( 427fn rename_reference(
@@ -450,7 +444,7 @@ fn rename_reference(
450 mark::hit!(rename_not_an_ident_ref); 444 mark::hit!(rename_not_an_ident_ref);
451 bail!("Invalid name `{}`: not an identifier", new_name) 445 bail!("Invalid name `{}`: not an identifier", new_name)
452 } 446 }
453 (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { 447 (IdentifierKind::ToSelf, ReferenceKind::SelfParam) => {
454 unreachable!("rename_self_to_param should've been called instead") 448 unreachable!("rename_self_to_param should've been called instead")
455 } 449 }
456 (IdentifierKind::ToSelf, _) => { 450 (IdentifierKind::ToSelf, _) => {
@@ -464,14 +458,12 @@ fn rename_reference(
464 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident), 458 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident),
465 } 459 }
466 460
467 let edit = refs 461 let mut source_change = SourceChange::default();
468 .into_iter() 462 source_change.extend(refs.into_iter().map(|(file_id, references)| {
469 .map(|(file_id, references)| { 463 source_edit_from_references(sema, file_id, &references, new_name)
470 source_edit_from_references(sema, file_id, &references, new_name) 464 }));
471 })
472 .collect::<Vec<_>>();
473 465
474 Ok(RangeInfo::new(range, SourceChange::from(edit))) 466 Ok(RangeInfo::new(range, source_change))
475} 467}
476 468
477#[cfg(test)] 469#[cfg(test)]
@@ -494,8 +486,8 @@ mod tests {
494 let mut text_edit_builder = TextEdit::builder(); 486 let mut text_edit_builder = TextEdit::builder();
495 let mut file_id: Option<FileId> = None; 487 let mut file_id: Option<FileId> = None;
496 for edit in source_change.info.source_file_edits { 488 for edit in source_change.info.source_file_edits {
497 file_id = Some(edit.file_id); 489 file_id = Some(edit.0);
498 for indel in edit.edit.into_iter() { 490 for indel in edit.1.into_iter() {
499 text_edit_builder.replace(indel.delete, indel.insert); 491 text_edit_builder.replace(indel.delete, indel.insert);
500 } 492 }
501 } 493 }
@@ -895,21 +887,18 @@ mod foo$0;
895 RangeInfo { 887 RangeInfo {
896 range: 4..7, 888 range: 4..7,
897 info: SourceChange { 889 info: SourceChange {
898 source_file_edits: [ 890 source_file_edits: {
899 SourceFileEdit { 891 FileId(
900 file_id: FileId( 892 1,
901 1, 893 ): TextEdit {
902 ), 894 indels: [
903 edit: TextEdit { 895 Indel {
904 indels: [ 896 insert: "foo2",
905 Indel { 897 delete: 4..7,
906 insert: "foo2", 898 },
907 delete: 4..7, 899 ],
908 },
909 ],
910 },
911 }, 900 },
912 ], 901 },
913 file_system_edits: [ 902 file_system_edits: [
914 MoveFile { 903 MoveFile {
915 src: FileId( 904 src: FileId(
@@ -950,34 +939,28 @@ use crate::foo$0::FooContent;
950 RangeInfo { 939 RangeInfo {
951 range: 11..14, 940 range: 11..14,
952 info: SourceChange { 941 info: SourceChange {
953 source_file_edits: [ 942 source_file_edits: {
954 SourceFileEdit { 943 FileId(
955 file_id: FileId( 944 0,
956 0, 945 ): TextEdit {
957 ), 946 indels: [
958 edit: TextEdit { 947 Indel {
959 indels: [ 948 insert: "quux",
960 Indel { 949 delete: 8..11,
961 insert: "quux", 950 },
962 delete: 8..11, 951 ],
963 },
964 ],
965 },
966 }, 952 },
967 SourceFileEdit { 953 FileId(
968 file_id: FileId( 954 2,
969 2, 955 ): TextEdit {
970 ), 956 indels: [
971 edit: TextEdit { 957 Indel {
972 indels: [ 958 insert: "quux",
973 Indel { 959 delete: 11..14,
974 insert: "quux", 960 },
975 delete: 11..14, 961 ],
976 },
977 ],
978 },
979 }, 962 },
980 ], 963 },
981 file_system_edits: [ 964 file_system_edits: [
982 MoveFile { 965 MoveFile {
983 src: FileId( 966 src: FileId(
@@ -1012,21 +995,18 @@ mod fo$0o;
1012 RangeInfo { 995 RangeInfo {
1013 range: 4..7, 996 range: 4..7,
1014 info: SourceChange { 997 info: SourceChange {
1015 source_file_edits: [ 998 source_file_edits: {
1016 SourceFileEdit { 999 FileId(
1017 file_id: FileId( 1000 0,
1018 0, 1001 ): TextEdit {
1019 ), 1002 indels: [
1020 edit: TextEdit { 1003 Indel {
1021 indels: [ 1004 insert: "foo2",
1022 Indel { 1005 delete: 4..7,
1023 insert: "foo2", 1006 },
1024 delete: 4..7, 1007 ],
1025 },
1026 ],
1027 },
1028 }, 1008 },
1029 ], 1009 },
1030 file_system_edits: [ 1010 file_system_edits: [
1031 MoveFile { 1011 MoveFile {
1032 src: FileId( 1012 src: FileId(
@@ -1062,21 +1042,18 @@ mod outer { mod fo$0o; }
1062 RangeInfo { 1042 RangeInfo {
1063 range: 16..19, 1043 range: 16..19,
1064 info: SourceChange { 1044 info: SourceChange {
1065 source_file_edits: [ 1045 source_file_edits: {
1066 SourceFileEdit { 1046 FileId(
1067 file_id: FileId( 1047 0,
1068 0, 1048 ): TextEdit {
1069 ), 1049 indels: [
1070 edit: TextEdit { 1050 Indel {
1071 indels: [ 1051 insert: "bar",
1072 Indel { 1052 delete: 16..19,
1073 insert: "bar", 1053 },
1074 delete: 16..19, 1054 ],
1075 },
1076 ],
1077 },
1078 }, 1055 },
1079 ], 1056 },
1080 file_system_edits: [ 1057 file_system_edits: [
1081 MoveFile { 1058 MoveFile {
1082 src: FileId( 1059 src: FileId(
@@ -1135,34 +1112,28 @@ pub mod foo$0;
1135 RangeInfo { 1112 RangeInfo {
1136 range: 8..11, 1113 range: 8..11,
1137 info: SourceChange { 1114 info: SourceChange {
1138 source_file_edits: [ 1115 source_file_edits: {
1139 SourceFileEdit { 1116 FileId(
1140 file_id: FileId( 1117 0,
1141 1, 1118 ): TextEdit {
1142 ), 1119 indels: [
1143 edit: TextEdit { 1120 Indel {
1144 indels: [ 1121 insert: "foo2",
1145 Indel { 1122 delete: 27..30,
1146 insert: "foo2", 1123 },
1147 delete: 8..11, 1124 ],
1148 },
1149 ],
1150 },
1151 }, 1125 },
1152 SourceFileEdit { 1126 FileId(
1153 file_id: FileId( 1127 1,
1154 0, 1128 ): TextEdit {
1155 ), 1129 indels: [
1156 edit: TextEdit { 1130 Indel {
1157 indels: [ 1131 insert: "foo2",
1158 Indel { 1132 delete: 8..11,
1159 insert: "foo2", 1133 },
1160 delete: 27..30, 1134 ],
1161 },
1162 ],
1163 },
1164 }, 1135 },
1165 ], 1136 },
1166 file_system_edits: [ 1137 file_system_edits: [
1167 MoveFile { 1138 MoveFile {
1168 src: FileId( 1139 src: FileId(
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 34bae49a8..87578e70a 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -226,35 +226,16 @@ pub(super) fn element(
226 T![unsafe] => h | HlMod::Unsafe, 226 T![unsafe] => h | HlMod::Unsafe,
227 T![true] | T![false] => HlTag::BoolLiteral.into(), 227 T![true] | T![false] => HlTag::BoolLiteral.into(),
228 T![self] => { 228 T![self] => {
229 let self_param_is_mut = element 229 let self_param = element.parent().and_then(ast::SelfParam::cast);
230 .parent() 230 if let Some(NameClass::Definition(def)) = self_param
231 .and_then(ast::SelfParam::cast) 231 .and_then(|self_param| NameClass::classify_self_param(sema, &self_param))
232 .and_then(|p| p.mut_token())
233 .is_some();
234 let self_path = &element
235 .parent()
236 .as_ref()
237 .and_then(SyntaxNode::parent)
238 .and_then(ast::Path::cast)
239 .and_then(|p| sema.resolve_path(&p));
240 let mut h = HlTag::Symbol(SymbolKind::SelfParam).into();
241 if self_param_is_mut
242 || matches!(self_path,
243 Some(hir::PathResolution::Local(local))
244 if local.is_self(db)
245 && (local.is_mut(db) || local.ty(db).is_mutable_reference())
246 )
247 { 232 {
248 h |= HlMod::Mutable 233 highlight_def(db, def) | HlMod::Definition
249 } 234 } else if element.ancestors().any(|it| it.kind() == USE_TREE) {
250 235 HlTag::Symbol(SymbolKind::SelfParam).into()
251 if let Some(hir::PathResolution::Local(local)) = self_path { 236 } else {
252 if is_consumed_lvalue(element, &local, db) { 237 return None;
253 h |= HlMod::Consuming;
254 }
255 } 238 }
256
257 h
258 } 239 }
259 T![ref] => element 240 T![ref] => element
260 .parent() 241 .parent()
@@ -345,7 +326,9 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
345 hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam), 326 hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam),
346 }, 327 },
347 Definition::Local(local) => { 328 Definition::Local(local) => {
348 let tag = if local.is_param(db) { 329 let tag = if local.is_self(db) {
330 HlTag::Symbol(SymbolKind::SelfParam)
331 } else if local.is_param(db) {
349 HlTag::Symbol(SymbolKind::ValueParam) 332 HlTag::Symbol(SymbolKind::ValueParam)
350 } else { 333 } else {
351 HlTag::Symbol(SymbolKind::Local) 334 HlTag::Symbol(SymbolKind::Local)
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index e36e6fc3f..d421a7803 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -42,16 +42,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
42 42
43<span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span> 43<span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span>
44 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 44 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
45 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 45 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
46<span class="brace">}</span> 46<span class="brace">}</span>
47 47
48<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> 48<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span>
49 <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 49 <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
50 <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 50 <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
51<span class="brace">}</span> 51<span class="brace">}</span>
52 52
53<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> 53<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span>
54 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 54 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
55 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 55 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
56<span class="brace">}</span> 56<span class="brace">}</span>
57 </code></pre> \ No newline at end of file 57 </code></pre> \ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 6dadda1c1..5e877df88 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -93,7 +93,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
93 <span class="comment documentation">/// ```sh</span> 93 <span class="comment documentation">/// ```sh</span>
94 <span class="comment documentation">/// echo 1</span> 94 <span class="comment documentation">/// echo 1</span>
95 <span class="comment documentation">/// ```</span> 95 <span class="comment documentation">/// ```</span>
96 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span> 96 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
97 <span class="bool_literal">true</span> 97 <span class="bool_literal">true</span>
98 <span class="brace">}</span> 98 <span class="brace">}</span>
99<span class="brace">}</span> 99<span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 9d4d6d4a0..036cb6c11 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -46,7 +46,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
46<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span> 46<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span>
47 47
48<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span> 48<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span>
49 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 49 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
50<span class="brace">}</span> 50<span class="brace">}</span>
51 51
52<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span> 52<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span>
@@ -61,11 +61,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
61<span class="brace">}</span> 61<span class="brace">}</span>
62 62
63<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> 63<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
64 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> 64 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
65<span class="brace">}</span> 65<span class="brace">}</span>
66 66
67<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> 67<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
68 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 68 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
69<span class="brace">}</span> 69<span class="brace">}</span>
70 70
71<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> 71<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 6b7447c46..237149566 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -66,25 +66,25 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
66<span class="brace">}</span> 66<span class="brace">}</span>
67 67
68<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> 68<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span>
69 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span> 69 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
70<span class="brace">}</span> 70<span class="brace">}</span>
71 71
72<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> 72<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span>
73 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 73 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
74 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 74 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
75 <span class="brace">}</span> 75 <span class="brace">}</span>
76<span class="brace">}</span> 76<span class="brace">}</span>
77 77
78<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> 78<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span>
79 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 79 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
80 <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span> 80 <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span>
81 <span class="brace">}</span> 81 <span class="brace">}</span>
82 82
83 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> 83 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
84 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> 84 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
85 <span class="brace">}</span> 85 <span class="brace">}</span>
86 86
87 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 87 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
88 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 88 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
89 <span class="brace">}</span> 89 <span class="brace">}</span>
90<span class="brace">}</span> 90<span class="brace">}</span>
@@ -95,15 +95,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
95<span class="brace">}</span> 95<span class="brace">}</span>
96 96
97<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span> 97<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span>
98 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> 98 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
99 <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span> 99 <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span>
100 <span class="brace">}</span> 100 <span class="brace">}</span>
101 101
102 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> 102 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
103 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> 103 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
104 <span class="brace">}</span> 104 <span class="brace">}</span>
105 105
106 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span> 106 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
107 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 107 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
108 <span class="brace">}</span> 108 <span class="brace">}</span>
109<span class="brace">}</span> 109<span class="brace">}</span>
@@ -213,7 +213,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
213<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> 213<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
214 214
215<span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span> 215<span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span>
216 <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span> 216 <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
217 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span> 217 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span>
218 <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> 218 <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
219 <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span> 219 <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs
index 1f26f8043..1d4bac7ad 100644
--- a/crates/ide/src/syntax_tree.rs
+++ b/crates/ide/src/syntax_tree.rs
@@ -1,7 +1,7 @@
1use ide_db::base_db::{FileId, SourceDatabase}; 1use ide_db::base_db::{FileId, SourceDatabase};
2use ide_db::RootDatabase; 2use ide_db::RootDatabase;
3use syntax::{ 3use syntax::{
4 algo, AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize, 4 AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize,
5}; 5};
6 6
7// Feature: Show Syntax Tree 7// Feature: Show Syntax Tree
@@ -21,7 +21,7 @@ pub(crate) fn syntax_tree(
21) -> String { 21) -> String {
22 let parse = db.parse(file_id); 22 let parse = db.parse(file_id);
23 if let Some(text_range) = text_range { 23 if let Some(text_range) = text_range {
24 let node = match algo::find_covering_element(parse.tree().syntax(), text_range) { 24 let node = match parse.tree().syntax().covering_element(text_range) {
25 NodeOrToken::Node(node) => node, 25 NodeOrToken::Node(node) => node,
26 NodeOrToken::Token(token) => { 26 NodeOrToken::Token(token) => {
27 if let Some(tree) = syntax_tree_for_string(&token, text_range) { 27 if let Some(tree) = syntax_tree_for_string(&token, text_range) {
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index 88c905003..e3c3aebac 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -15,8 +15,10 @@
15 15
16mod on_enter; 16mod on_enter;
17 17
18use ide_db::base_db::{FilePosition, SourceDatabase}; 18use ide_db::{
19use ide_db::{source_change::SourceFileEdit, RootDatabase}; 19 base_db::{FilePosition, SourceDatabase},
20 RootDatabase,
21};
20use syntax::{ 22use syntax::{
21 algo::find_node_at_offset, 23 algo::find_node_at_offset,
22 ast::{self, edit::IndentLevel, AstToken}, 24 ast::{self, edit::IndentLevel, AstToken},
@@ -56,7 +58,7 @@ pub(crate) fn on_char_typed(
56 let file = &db.parse(position.file_id).tree(); 58 let file = &db.parse(position.file_id).tree();
57 assert_eq!(file.syntax().text().char_at(position.offset), Some(char_typed)); 59 assert_eq!(file.syntax().text().char_at(position.offset), Some(char_typed));
58 let edit = on_char_typed_inner(file, position.offset, char_typed)?; 60 let edit = on_char_typed_inner(file, position.offset, char_typed)?;
59 Some(SourceFileEdit { file_id: position.file_id, edit }.into()) 61 Some(SourceChange::from_text_edit(position.file_id, edit))
60} 62}
61 63
62fn on_char_typed_inner(file: &SourceFile, offset: TextSize, char_typed: char) -> Option<TextEdit> { 64fn on_char_typed_inner(file: &SourceFile, offset: TextSize, char_typed: char) -> Option<TextEdit> {