aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/Cargo.toml1
-rw-r--r--crates/ra_ide_api/src/change.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs150
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_literal.rs28
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs17
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs68
-rw-r--r--crates/ra_ide_api/src/db.rs5
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs3
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs74
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs2
-rw-r--r--crates/ra_ide_api/src/references/rename.rs3
-rw-r--r--crates/ra_ide_api/src/runnables.rs14
-rw-r--r--crates/ra_ide_api/src/source_change.rs2
13 files changed, 340 insertions, 31 deletions
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml
index bf6ef12f3..fa353b5dd 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide_api/Cargo.toml
@@ -12,7 +12,6 @@ format-buf = "1.0.0"
12itertools = "0.8.0" 12itertools = "0.8.0"
13join_to_string = "0.1.3" 13join_to_string = "0.1.3"
14log = "0.4.5" 14log = "0.4.5"
15relative-path = "1.0.0"
16rayon = "1.0.2" 15rayon = "1.0.2"
17fst = { version = "0.3.1", default-features = false } 16fst = { version = "0.3.1", default-features = false }
18rustc-hash = "1.0" 17rustc-hash = "1.0"
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 39c5946c7..4416421ae 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -4,13 +4,13 @@ use std::{fmt, sync::Arc, time};
4 4
5use ra_db::{ 5use ra_db::{
6 salsa::{Database, Durability, SweepStrategy}, 6 salsa::{Database, Durability, SweepStrategy},
7 CrateGraph, CrateId, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, 7 CrateGraph, CrateId, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot,
8 SourceRootId,
8}; 9};
9use ra_prof::{memory_usage, profile, Bytes}; 10use ra_prof::{memory_usage, profile, Bytes};
10use ra_syntax::SourceFile; 11use ra_syntax::SourceFile;
11#[cfg(not(feature = "wasm"))] 12#[cfg(not(feature = "wasm"))]
12use rayon::prelude::*; 13use rayon::prelude::*;
13use relative_path::RelativePathBuf;
14use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
15 15
16use crate::{ 16use crate::{
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index a58fdc036..09ca40179 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -18,15 +18,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
18 match def { 18 match def {
19 hir::ModuleDef::Module(module) => { 19 hir::ModuleDef::Module(module) => {
20 let module_scope = module.scope(ctx.db); 20 let module_scope = module.scope(ctx.db);
21 for (name, res) in module_scope.entries() { 21 for (name, def, import) in module_scope {
22 if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.take_types() { 22 if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def {
23 if ctx.use_item_syntax.is_some() { 23 if ctx.use_item_syntax.is_some() {
24 tested_by!(dont_complete_primitive_in_use); 24 tested_by!(dont_complete_primitive_in_use);
25 continue; 25 continue;
26 } 26 }
27 } 27 }
28 if Some(module) == ctx.module { 28 if Some(module) == ctx.module {
29 if let Some(import) = res.import { 29 if let Some(import) = import {
30 if let Either::A(use_tree) = module.import_source(ctx.db, import) { 30 if let Either::A(use_tree) = module.import_source(ctx.db, import) {
31 if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { 31 if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
32 // for `use self::foo<|>`, don't suggest `foo` as a completion 32 // for `use self::foo<|>`, don't suggest `foo` as a completion
@@ -36,7 +36,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
36 } 36 }
37 } 37 }
38 } 38 }
39 acc.add_resolution(ctx, name.to_string(), &res.def.into()); 39 acc.add_resolution(ctx, name.to_string(), &def);
40 } 40 }
41 } 41 }
42 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { 42 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
@@ -50,23 +50,46 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
50 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 50 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
51 _ => unreachable!(), 51 _ => unreachable!(),
52 }; 52 };
53 ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
54 match item {
55 hir::AssocItem::Function(func) => {
56 let data = func.data(ctx.db);
57 if !data.has_self_param() {
58 acc.add_function(ctx, func);
59 }
60 }
61 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
62 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
63 }
64 None::<()>
65 });
66 // Iterate assoc types separately
67 // FIXME: complete T::AssocType
53 let krate = ctx.module.map(|m| m.krate()); 68 let krate = ctx.module.map(|m| m.krate());
54 if let Some(krate) = krate { 69 if let Some(krate) = krate {
55 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
56 match item { 71 match item {
57 hir::AssocItem::Function(func) => { 72 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
58 let data = func.data(ctx.db);
59 if !data.has_self_param() {
60 acc.add_function(ctx, func);
61 }
62 }
63 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
64 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), 73 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
65 } 74 }
66 None::<()> 75 None::<()>
67 }); 76 });
68 } 77 }
69 } 78 }
79 hir::ModuleDef::Trait(t) => {
80 for item in t.items(ctx.db) {
81 match item {
82 hir::AssocItem::Function(func) => {
83 let data = func.data(ctx.db);
84 if !data.has_self_param() {
85 acc.add_function(ctx, func);
86 }
87 }
88 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
89 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
90 }
91 }
92 }
70 _ => {} 93 _ => {}
71 }; 94 };
72} 95}
@@ -559,6 +582,111 @@ mod tests {
559 } 582 }
560 583
561 #[test] 584 #[test]
585 fn completes_trait_associated_method_1() {
586 assert_debug_snapshot!(
587 do_reference_completion(
588 "
589 //- /lib.rs
590 trait Trait {
591 /// A trait method
592 fn m();
593 }
594
595 fn foo() { let _ = Trait::<|> }
596 "
597 ),
598 @r###"
599 [
600 CompletionItem {
601 label: "m()",
602 source_range: [73; 73),
603 delete: [73; 73),
604 insert: "m()$0",
605 kind: Function,
606 lookup: "m",
607 detail: "fn m()",
608 documentation: Documentation(
609 "A trait method",
610 ),
611 },
612 ]
613 "###
614 );
615 }
616
617 #[test]
618 fn completes_trait_associated_method_2() {
619 assert_debug_snapshot!(
620 do_reference_completion(
621 "
622 //- /lib.rs
623 trait Trait {
624 /// A trait method
625 fn m();
626 }
627
628 struct S;
629 impl Trait for S {}
630
631 fn foo() { let _ = S::<|> }
632 "
633 ),
634 @r###"
635 [
636 CompletionItem {
637 label: "m()",
638 source_range: [99; 99),
639 delete: [99; 99),
640 insert: "m()$0",
641 kind: Function,
642 lookup: "m",
643 detail: "fn m()",
644 documentation: Documentation(
645 "A trait method",
646 ),
647 },
648 ]
649 "###
650 );
651 }
652
653 #[test]
654 fn completes_trait_associated_method_3() {
655 assert_debug_snapshot!(
656 do_reference_completion(
657 "
658 //- /lib.rs
659 trait Trait {
660 /// A trait method
661 fn m();
662 }
663
664 struct S;
665 impl Trait for S {}
666
667 fn foo() { let _ = <S as Trait>::<|> }
668 "
669 ),
670 @r###"
671 [
672 CompletionItem {
673 label: "m()",
674 source_range: [110; 110),
675 delete: [110; 110),
676 insert: "m()$0",
677 kind: Function,
678 lookup: "m",
679 detail: "fn m()",
680 documentation: Documentation(
681 "A trait method",
682 ),
683 },
684 ]
685 "###
686 );
687 }
688
689 #[test]
562 fn completes_type_alias() { 690 fn completes_type_alias() {
563 assert_debug_snapshot!( 691 assert_debug_snapshot!(
564 do_reference_completion( 692 do_reference_completion(
diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs
index 4406695d5..0295b8101 100644
--- a/crates/ra_ide_api/src/completion/complete_record_literal.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs
@@ -32,6 +32,34 @@ mod tests {
32 } 32 }
33 33
34 #[test] 34 #[test]
35 fn test_record_literal_deprecated_field() {
36 let completions = complete(
37 r"
38 struct A {
39 #[deprecated]
40 the_field: u32,
41 }
42 fn foo() {
43 A { the<|> }
44 }
45 ",
46 );
47 assert_debug_snapshot!(completions, @r###"
48 â‹®[
49 â‹® CompletionItem {
50 â‹® label: "the_field",
51 â‹® source_range: [142; 145),
52 â‹® delete: [142; 145),
53 â‹® insert: "the_field",
54 â‹® kind: Field,
55 â‹® detail: "u32",
56 â‹® deprecated: true,
57 â‹® },
58 â‹®]
59 "###);
60 }
61
62 #[test]
35 fn test_record_literal_field() { 63 fn test_record_literal_field() {
36 let completions = complete( 64 let completions = complete(
37 r" 65 r"
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index 5c9c44704..93f336370 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -44,6 +44,9 @@ pub struct CompletionItem {
44 /// Additional info to show in the UI pop up. 44 /// Additional info to show in the UI pop up.
45 detail: Option<String>, 45 detail: Option<String>,
46 documentation: Option<Documentation>, 46 documentation: Option<Documentation>,
47
48 /// Whether this item is marked as deprecated
49 deprecated: bool,
47} 50}
48 51
49// We use custom debug for CompletionItem to make `insta`'s diffs more readable. 52// We use custom debug for CompletionItem to make `insta`'s diffs more readable.
@@ -70,6 +73,9 @@ impl fmt::Debug for CompletionItem {
70 if let Some(documentation) = self.documentation() { 73 if let Some(documentation) = self.documentation() {
71 s.field("documentation", &documentation); 74 s.field("documentation", &documentation);
72 } 75 }
76 if self.deprecated {
77 s.field("deprecated", &true);
78 }
73 s.finish() 79 s.finish()
74 } 80 }
75} 81}
@@ -132,6 +138,7 @@ impl CompletionItem {
132 lookup: None, 138 lookup: None,
133 kind: None, 139 kind: None,
134 text_edit: None, 140 text_edit: None,
141 deprecated: None,
135 } 142 }
136 } 143 }
137 /// What user sees in pop-up in the UI. 144 /// What user sees in pop-up in the UI.
@@ -166,6 +173,10 @@ impl CompletionItem {
166 pub fn kind(&self) -> Option<CompletionItemKind> { 173 pub fn kind(&self) -> Option<CompletionItemKind> {
167 self.kind 174 self.kind
168 } 175 }
176
177 pub fn deprecated(&self) -> bool {
178 self.deprecated
179 }
169} 180}
170 181
171/// A helper to make `CompletionItem`s. 182/// A helper to make `CompletionItem`s.
@@ -181,6 +192,7 @@ pub(crate) struct Builder {
181 lookup: Option<String>, 192 lookup: Option<String>,
182 kind: Option<CompletionItemKind>, 193 kind: Option<CompletionItemKind>,
183 text_edit: Option<TextEdit>, 194 text_edit: Option<TextEdit>,
195 deprecated: Option<bool>,
184} 196}
185 197
186impl Builder { 198impl Builder {
@@ -208,6 +220,7 @@ impl Builder {
208 lookup: self.lookup, 220 lookup: self.lookup,
209 kind: self.kind, 221 kind: self.kind,
210 completion_kind: self.completion_kind, 222 completion_kind: self.completion_kind,
223 deprecated: self.deprecated.unwrap_or(false),
211 } 224 }
212 } 225 }
213 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { 226 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
@@ -254,6 +267,10 @@ impl Builder {
254 self.documentation = docs.map(Into::into); 267 self.documentation = docs.map(Into::into);
255 self 268 self
256 } 269 }
270 pub(crate) fn set_deprecated(mut self, deprecated: bool) -> Builder {
271 self.deprecated = Some(deprecated);
272 self
273 }
257} 274}
258 275
259impl<'a> Into<CompletionItem> for Builder { 276impl<'a> Into<CompletionItem> for Builder {
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 65bb639ed..cb55d1875 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -2,7 +2,7 @@
2 2
3use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; 3use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
4use join_to_string::join; 4use join_to_string::join;
5use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::{AttrsOwner, NameOwner};
6use test_utils::tested_by; 6use test_utils::tested_by;
7 7
8use crate::completion::{ 8use crate::completion::{
@@ -18,6 +18,11 @@ impl Completions {
18 field: hir::StructField, 18 field: hir::StructField,
19 substs: &hir::Substs, 19 substs: &hir::Substs,
20 ) { 20 ) {
21 let ast_node = field.source(ctx.db).ast;
22 let is_deprecated = match ast_node {
23 hir::FieldSource::Named(m) => is_deprecated(m),
24 hir::FieldSource::Pos(m) => is_deprecated(m),
25 };
21 CompletionItem::new( 26 CompletionItem::new(
22 CompletionKind::Reference, 27 CompletionKind::Reference,
23 ctx.source_range(), 28 ctx.source_range(),
@@ -26,6 +31,7 @@ impl Completions {
26 .kind(CompletionItemKind::Field) 31 .kind(CompletionItemKind::Field)
27 .detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string()) 32 .detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string())
28 .set_documentation(field.docs(ctx.db)) 33 .set_documentation(field.docs(ctx.db))
34 .set_deprecated(is_deprecated)
29 .add_to(self); 35 .add_to(self);
30 } 36 }
31 37
@@ -179,6 +185,7 @@ impl Completions {
179 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), &macro_declaration) 185 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), &macro_declaration)
180 .kind(CompletionItemKind::Macro) 186 .kind(CompletionItemKind::Macro)
181 .set_documentation(docs.clone()) 187 .set_documentation(docs.clone())
188 .set_deprecated(is_deprecated(ast_node))
182 .detail(detail); 189 .detail(detail);
183 190
184 builder = if ctx.use_item_syntax.is_some() { 191 builder = if ctx.use_item_syntax.is_some() {
@@ -211,6 +218,7 @@ impl Completions {
211 CompletionItemKind::Function 218 CompletionItemKind::Function
212 }) 219 })
213 .set_documentation(func.docs(ctx.db)) 220 .set_documentation(func.docs(ctx.db))
221 .set_deprecated(is_deprecated(ast_node))
214 .detail(detail); 222 .detail(detail);
215 223
216 // Add `<>` for generic types 224 // Add `<>` for generic types
@@ -242,6 +250,7 @@ impl Completions {
242 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) 250 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
243 .kind(CompletionItemKind::Const) 251 .kind(CompletionItemKind::Const)
244 .set_documentation(constant.docs(ctx.db)) 252 .set_documentation(constant.docs(ctx.db))
253 .set_deprecated(is_deprecated(ast_node))
245 .detail(detail) 254 .detail(detail)
246 .add_to(self); 255 .add_to(self);
247 } 256 }
@@ -257,11 +266,13 @@ impl Completions {
257 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) 266 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
258 .kind(CompletionItemKind::TypeAlias) 267 .kind(CompletionItemKind::TypeAlias)
259 .set_documentation(type_alias.docs(ctx.db)) 268 .set_documentation(type_alias.docs(ctx.db))
269 .set_deprecated(is_deprecated(type_def))
260 .detail(detail) 270 .detail(detail)
261 .add_to(self); 271 .add_to(self);
262 } 272 }
263 273
264 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { 274 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
275 let is_deprecated = is_deprecated(variant.source(ctx.db).ast);
265 let name = match variant.name(ctx.db) { 276 let name = match variant.name(ctx.db) {
266 Some(it) => it, 277 Some(it) => it,
267 None => return, 278 None => return,
@@ -274,11 +285,16 @@ impl Completions {
274 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) 285 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
275 .kind(CompletionItemKind::EnumVariant) 286 .kind(CompletionItemKind::EnumVariant)
276 .set_documentation(variant.docs(ctx.db)) 287 .set_documentation(variant.docs(ctx.db))
288 .set_deprecated(is_deprecated)
277 .detail(detail) 289 .detail(detail)
278 .add_to(self); 290 .add_to(self);
279 } 291 }
280} 292}
281 293
294fn is_deprecated(node: impl AttrsOwner) -> bool {
295 node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated")
296}
297
282fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { 298fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
283 let subst = db.generic_defaults(def); 299 let subst = db.generic_defaults(def);
284 subst.iter().any(|ty| ty == &Ty::Unknown) 300 subst.iter().any(|ty| ty == &Ty::Unknown)
@@ -296,6 +312,56 @@ mod tests {
296 } 312 }
297 313
298 #[test] 314 #[test]
315 fn sets_deprecated_flag_in_completion_items() {
316 assert_debug_snapshot!(
317 do_reference_completion(
318 r#"
319 #[deprecated]
320 fn something_deprecated() {}
321
322 #[deprecated(since = "1.0.0")]
323 fn something_else_deprecated() {}
324
325 fn main() { som<|> }
326 "#,
327 ),
328 @r###"
329 [
330 CompletionItem {
331 label: "main()",
332 source_range: [203; 206),
333 delete: [203; 206),
334 insert: "main()$0",
335 kind: Function,
336 lookup: "main",
337 detail: "fn main()",
338 },
339 CompletionItem {
340 label: "something_deprecated()",
341 source_range: [203; 206),
342 delete: [203; 206),
343 insert: "something_deprecated()$0",
344 kind: Function,
345 lookup: "something_deprecated",
346 detail: "fn something_deprecated()",
347 deprecated: true,
348 },
349 CompletionItem {
350 label: "something_else_deprecated()",
351 source_range: [203; 206),
352 delete: [203; 206),
353 insert: "something_else_deprecated()$0",
354 kind: Function,
355 lookup: "something_else_deprecated",
356 detail: "fn something_else_deprecated()",
357 deprecated: true,
358 },
359 ]
360 "###
361 );
362 }
363
364 #[test]
299 fn inserts_parens_for_function_calls() { 365 fn inserts_parens_for_function_calls() {
300 covers!(inserts_parens_for_function_calls); 366 covers!(inserts_parens_for_function_calls);
301 assert_debug_snapshot!( 367 assert_debug_snapshot!(
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index 785e71808..c96465b6a 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -4,10 +4,9 @@ use std::sync::Arc;
4 4
5use ra_db::{ 5use ra_db::{
6 salsa::{self, Database, Durability}, 6 salsa::{self, Database, Durability},
7 Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, 7 Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath,
8 SourceDatabaseExt, SourceRootId, 8 SourceDatabase, SourceDatabaseExt, SourceRootId,
9}; 9};
10use relative_path::RelativePath;
11use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
12 11
13use crate::{ 12use crate::{
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 1f1f5cd74..2890a3d2b 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -4,7 +4,7 @@ use std::cell::RefCell;
4 4
5use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}; 5use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink};
6use itertools::Itertools; 6use itertools::Itertools;
7use ra_db::{SourceDatabase, SourceDatabaseExt}; 7use ra_db::{RelativePath, SourceDatabase, SourceDatabaseExt};
8use ra_prof::profile; 8use ra_prof::profile;
9use ra_syntax::{ 9use ra_syntax::{
10 algo, 10 algo,
@@ -12,7 +12,6 @@ use ra_syntax::{
12 Location, SyntaxNode, TextRange, T, 12 Location, SyntaxNode, TextRange, T,
13}; 13};
14use ra_text_edit::{TextEdit, TextEditBuilder}; 14use ra_text_edit::{TextEdit, TextEditBuilder};
15use relative_path::RelativePath;
16 15
17use crate::{db::RootDatabase, Diagnostic, FileId, FileSystemEdit, SourceChange, SourceFileEdit}; 16use crate::{db::RootDatabase, Diagnostic, FileId, FileSystemEdit, SourceChange, SourceFileEdit};
18 17
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 1f3fa6c57..c1ce54bea 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -316,6 +316,25 @@ mod tests {
316 } 316 }
317 317
318 #[test] 318 #[test]
319 fn goto_definition_works_for_macros_in_use_tree() {
320 check_goto(
321 "
322 //- /lib.rs
323 use foo::foo<|>;
324
325 //- /foo/lib.rs
326 #[macro_export]
327 macro_rules! foo {
328 () => {
329 {}
330 };
331 }
332 ",
333 "foo MACRO_CALL FileId(2) [0; 66) [29; 32)",
334 );
335 }
336
337 #[test]
319 fn goto_definition_works_for_methods() { 338 fn goto_definition_works_for_methods() {
320 covers!(goto_definition_works_for_methods); 339 covers!(goto_definition_works_for_methods);
321 check_goto( 340 check_goto(
@@ -371,6 +390,61 @@ mod tests {
371 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", 390 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
372 ); 391 );
373 } 392 }
393
394 #[test]
395 fn goto_definition_works_for_ufcs_inherent_methods() {
396 check_goto(
397 "
398 //- /lib.rs
399 struct Foo;
400 impl Foo {
401 fn frobnicate() { }
402 }
403
404 fn bar(foo: &Foo) {
405 Foo::frobnicate<|>();
406 }
407 ",
408 "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)",
409 );
410 }
411
412 #[test]
413 fn goto_definition_works_for_ufcs_trait_methods_through_traits() {
414 check_goto(
415 "
416 //- /lib.rs
417 trait Foo {
418 fn frobnicate();
419 }
420
421 fn bar() {
422 Foo::frobnicate<|>();
423 }
424 ",
425 "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)",
426 );
427 }
428
429 #[test]
430 fn goto_definition_works_for_ufcs_trait_methods_through_self() {
431 check_goto(
432 "
433 //- /lib.rs
434 struct Foo;
435 trait Trait {
436 fn frobnicate();
437 }
438 impl Trait for Foo {}
439
440 fn bar() {
441 Foo::frobnicate<|>();
442 }
443 ",
444 "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)",
445 );
446 }
447
374 #[test] 448 #[test]
375 fn goto_definition_on_self() { 449 fn goto_definition_on_self() {
376 check_goto( 450 check_goto(
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 80b71894c..2b1c96dbf 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -3,7 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_cfg::CfgOptions; 5use ra_cfg::CfgOptions;
6use relative_path::RelativePathBuf; 6use ra_db::RelativePathBuf;
7use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; 7use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
8 8
9use crate::{ 9use crate::{
diff --git a/crates/ra_ide_api/src/references/rename.rs b/crates/ra_ide_api/src/references/rename.rs
index a8783d7a0..11f81cbb3 100644
--- a/crates/ra_ide_api/src/references/rename.rs
+++ b/crates/ra_ide_api/src/references/rename.rs
@@ -1,10 +1,9 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::ModuleSource; 3use hir::ModuleSource;
4use ra_db::{SourceDatabase, SourceDatabaseExt}; 4use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt};
5use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode};
6use ra_text_edit::TextEdit; 6use ra_text_edit::TextEdit;
7use relative_path::{RelativePath, RelativePathBuf};
8 7
9use crate::{ 8use crate::{
10 db::RootDatabase, FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, 9 db::RootDatabase, FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange,
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index 910883da7..1b5c8deea 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -4,7 +4,7 @@ use itertools::Itertools;
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner}, 6 ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner},
7 SyntaxNode, TextRange, 7 match_ast, SyntaxNode, TextRange,
8}; 8};
9 9
10use crate::{db::RootDatabase, FileId}; 10use crate::{db::RootDatabase, FileId};
@@ -29,12 +29,12 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
29} 29}
30 30
31fn runnable(db: &RootDatabase, file_id: FileId, item: SyntaxNode) -> Option<Runnable> { 31fn runnable(db: &RootDatabase, file_id: FileId, item: SyntaxNode) -> Option<Runnable> {
32 if let Some(fn_def) = ast::FnDef::cast(item.clone()) { 32 match_ast! {
33 runnable_fn(fn_def) 33 match item {
34 } else if let Some(m) = ast::Module::cast(item) { 34 ast::FnDef(it) => { runnable_fn(it) },
35 runnable_mod(db, file_id, m) 35 ast::Module(it) => { runnable_mod(db, file_id, it) },
36 } else { 36 _ => { None },
37 None 37 }
38 } 38 }
39} 39}
40 40
diff --git a/crates/ra_ide_api/src/source_change.rs b/crates/ra_ide_api/src/source_change.rs
index 4e63bbf6f..f5f7f8807 100644
--- a/crates/ra_ide_api/src/source_change.rs
+++ b/crates/ra_ide_api/src/source_change.rs
@@ -3,8 +3,8 @@
3//! 3//!
4//! It can be viewed as a dual for `AnalysisChange`. 4//! It can be viewed as a dual for `AnalysisChange`.
5 5
6use ra_db::RelativePathBuf;
6use ra_text_edit::TextEdit; 7use ra_text_edit::TextEdit;
7use relative_path::RelativePathBuf;
8 8
9use crate::{FileId, FilePosition, SourceRootId, TextUnit}; 9use crate::{FileId, FilePosition, SourceRootId, TextUnit};
10 10