diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model/docs.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_scope.rs | 154 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_context.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/presentation.rs | 136 | ||||
-rw-r--r-- | crates/ra_ide_api/src/marks.rs | 1 |
5 files changed, 222 insertions, 96 deletions
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs index 9675e397f..8533b4f5e 100644 --- a/crates/ra_hir/src/code_model/docs.rs +++ b/crates/ra_hir/src/code_model/docs.rs | |||
@@ -6,21 +6,19 @@ use ra_syntax::ast; | |||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | db::{AstDatabase, DefDatabase, HirDatabase}, | 8 | db::{AstDatabase, DefDatabase, HirDatabase}, |
9 | Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static, Struct, | 9 | Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static, |
10 | StructField, Trait, TypeAlias, Union, | 10 | Struct, StructField, Trait, TypeAlias, Union, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 13 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
14 | pub enum DocDef { | 14 | pub enum DocDef { |
15 | Module(Module), | 15 | Module(Module), |
16 | StructField(StructField), | 16 | StructField(StructField), |
17 | Struct(Struct), | 17 | Adt(Adt), |
18 | Enum(Enum), | ||
19 | EnumVariant(EnumVariant), | 18 | EnumVariant(EnumVariant), |
20 | Static(Static), | 19 | Static(Static), |
21 | Const(Const), | 20 | Const(Const), |
22 | Function(Function), | 21 | Function(Function), |
23 | Union(Union), | ||
24 | Trait(Trait), | 22 | Trait(Trait), |
25 | TypeAlias(TypeAlias), | 23 | TypeAlias(TypeAlias), |
26 | MacroDef(MacroDef), | 24 | MacroDef(MacroDef), |
@@ -29,13 +27,11 @@ pub enum DocDef { | |||
29 | impl_froms!( | 27 | impl_froms!( |
30 | DocDef: Module, | 28 | DocDef: Module, |
31 | StructField, | 29 | StructField, |
32 | Struct, | 30 | Adt(Struct, Enum, Union), |
33 | Enum, | ||
34 | EnumVariant, | 31 | EnumVariant, |
35 | Static, | 32 | Static, |
36 | Const, | 33 | Const, |
37 | Function, | 34 | Function, |
38 | Union, | ||
39 | Trait, | 35 | Trait, |
40 | TypeAlias, | 36 | TypeAlias, |
41 | MacroDef | 37 | MacroDef |
@@ -79,13 +75,15 @@ pub(crate) fn documentation_query( | |||
79 | FieldSource::Named(named) => docs_from_ast(&named), | 75 | FieldSource::Named(named) => docs_from_ast(&named), |
80 | FieldSource::Pos(..) => None, | 76 | FieldSource::Pos(..) => None, |
81 | }, | 77 | }, |
82 | DocDef::Struct(it) => docs_from_ast(&it.source(db).ast), | 78 | DocDef::Adt(it) => match it { |
83 | DocDef::Enum(it) => docs_from_ast(&it.source(db).ast), | 79 | Adt::Struct(it) => docs_from_ast(&it.source(db).ast), |
80 | Adt::Enum(it) => docs_from_ast(&it.source(db).ast), | ||
81 | Adt::Union(it) => docs_from_ast(&it.source(db).ast), | ||
82 | }, | ||
84 | DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).ast), | 83 | DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).ast), |
85 | DocDef::Static(it) => docs_from_ast(&it.source(db).ast), | 84 | DocDef::Static(it) => docs_from_ast(&it.source(db).ast), |
86 | DocDef::Const(it) => docs_from_ast(&it.source(db).ast), | 85 | DocDef::Const(it) => docs_from_ast(&it.source(db).ast), |
87 | DocDef::Function(it) => docs_from_ast(&it.source(db).ast), | 86 | DocDef::Function(it) => docs_from_ast(&it.source(db).ast), |
88 | DocDef::Union(it) => docs_from_ast(&it.source(db).ast), | ||
89 | DocDef::Trait(it) => docs_from_ast(&it.source(db).ast), | 87 | DocDef::Trait(it) => docs_from_ast(&it.source(db).ast), |
90 | DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).ast), | 88 | DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).ast), |
91 | DocDef::MacroDef(it) => docs_from_ast(&it.source(db).ast), | 89 | DocDef::MacroDef(it) => docs_from_ast(&it.source(db).ast), |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 38a6c3d37..84826cdcc 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -290,22 +290,24 @@ mod tests { | |||
290 | } | 290 | } |
291 | " | 291 | " |
292 | ), | 292 | ), |
293 | @r###"[ | 293 | @r###" |
294 | CompletionItem { | 294 | [ |
295 | label: "T", | 295 | CompletionItem { |
296 | source_range: [54; 54), | 296 | label: "T", |
297 | delete: [54; 54), | 297 | source_range: [54; 54), |
298 | insert: "T", | 298 | delete: [54; 54), |
299 | kind: TypeParam, | 299 | insert: "T", |
300 | }, | 300 | kind: TypeParam, |
301 | CompletionItem { | 301 | }, |
302 | label: "X", | 302 | CompletionItem { |
303 | source_range: [54; 54), | 303 | label: "X", |
304 | delete: [54; 54), | 304 | source_range: [54; 54), |
305 | insert: "X", | 305 | delete: [54; 54), |
306 | kind: Struct, | 306 | insert: "X<$0>", |
307 | }, | 307 | kind: Struct, |
308 | ]"### | 308 | }, |
309 | ] | ||
310 | "### | ||
309 | ); | 311 | ); |
310 | } | 312 | } |
311 | 313 | ||
@@ -319,22 +321,24 @@ mod tests { | |||
319 | } | 321 | } |
320 | " | 322 | " |
321 | ), | 323 | ), |
322 | @r###"[ | 324 | @r###" |
323 | CompletionItem { | 325 | [ |
324 | label: "Self", | 326 | CompletionItem { |
325 | source_range: [48; 48), | 327 | label: "Self", |
326 | delete: [48; 48), | 328 | source_range: [48; 48), |
327 | insert: "Self", | 329 | delete: [48; 48), |
328 | kind: TypeParam, | 330 | insert: "Self", |
329 | }, | 331 | kind: TypeParam, |
330 | CompletionItem { | 332 | }, |
331 | label: "X", | 333 | CompletionItem { |
332 | source_range: [48; 48), | 334 | label: "X", |
333 | delete: [48; 48), | 335 | source_range: [48; 48), |
334 | insert: "X", | 336 | delete: [48; 48), |
335 | kind: Enum, | 337 | insert: "X", |
336 | }, | 338 | kind: Enum, |
337 | ]"### | 339 | }, |
340 | ] | ||
341 | "### | ||
338 | ); | 342 | ); |
339 | } | 343 | } |
340 | 344 | ||
@@ -442,23 +446,25 @@ mod tests { | |||
442 | fn x() -> <|> | 446 | fn x() -> <|> |
443 | " | 447 | " |
444 | ), | 448 | ), |
445 | @r###"[ | 449 | @r###" |
446 | CompletionItem { | 450 | [ |
447 | label: "Foo", | 451 | CompletionItem { |
448 | source_range: [55; 55), | 452 | label: "Foo", |
449 | delete: [55; 55), | 453 | source_range: [55; 55), |
450 | insert: "Foo", | 454 | delete: [55; 55), |
451 | kind: Struct, | 455 | insert: "Foo", |
452 | }, | 456 | kind: Struct, |
453 | CompletionItem { | 457 | }, |
454 | label: "x", | 458 | CompletionItem { |
455 | source_range: [55; 55), | 459 | label: "x", |
456 | delete: [55; 55), | 460 | source_range: [55; 55), |
457 | insert: "x()$0", | 461 | delete: [55; 55), |
458 | kind: Function, | 462 | insert: "x()$0", |
459 | detail: "fn x()", | 463 | kind: Function, |
460 | }, | 464 | detail: "fn x()", |
461 | ]"### | 465 | }, |
466 | ] | ||
467 | "### | ||
462 | ); | 468 | ); |
463 | } | 469 | } |
464 | 470 | ||
@@ -538,30 +544,32 @@ mod tests { | |||
538 | } | 544 | } |
539 | " | 545 | " |
540 | ), | 546 | ), |
541 | @r#"[ | 547 | @r###" |
542 | CompletionItem { | 548 | [ |
543 | label: "Option", | 549 | CompletionItem { |
544 | source_range: [18; 18), | 550 | label: "Option", |
545 | delete: [18; 18), | 551 | source_range: [18; 18), |
546 | insert: "Option", | 552 | delete: [18; 18), |
547 | kind: Struct, | 553 | insert: "Option", |
548 | }, | 554 | kind: Struct, |
549 | CompletionItem { | 555 | }, |
550 | label: "foo", | 556 | CompletionItem { |
551 | source_range: [18; 18), | 557 | label: "foo", |
552 | delete: [18; 18), | 558 | source_range: [18; 18), |
553 | insert: "foo()$0", | 559 | delete: [18; 18), |
554 | kind: Function, | 560 | insert: "foo()$0", |
555 | detail: "fn foo()", | 561 | kind: Function, |
556 | }, | 562 | detail: "fn foo()", |
557 | CompletionItem { | 563 | }, |
558 | label: "std", | 564 | CompletionItem { |
559 | source_range: [18; 18), | 565 | label: "std", |
560 | delete: [18; 18), | 566 | source_range: [18; 18), |
561 | insert: "std", | 567 | delete: [18; 18), |
562 | kind: Module, | 568 | insert: "std", |
563 | }, | 569 | kind: Module, |
564 | ]"# | 570 | }, |
571 | ] | ||
572 | "### | ||
565 | ); | 573 | ); |
566 | } | 574 | } |
567 | 575 | ||
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index e9ad06965..73f3f3960 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -40,6 +40,8 @@ pub(crate) struct CompletionContext<'a> { | |||
40 | pub(super) dot_receiver: Option<ast::Expr>, | 40 | pub(super) dot_receiver: Option<ast::Expr>, |
41 | /// If this is a call (method or function) in particular, i.e. the () are already there. | 41 | /// If this is a call (method or function) in particular, i.e. the () are already there. |
42 | pub(super) is_call: bool, | 42 | pub(super) is_call: bool, |
43 | pub(super) is_path_type: bool, | ||
44 | pub(super) has_type_args: bool, | ||
43 | } | 45 | } |
44 | 46 | ||
45 | impl<'a> CompletionContext<'a> { | 47 | impl<'a> CompletionContext<'a> { |
@@ -76,6 +78,8 @@ impl<'a> CompletionContext<'a> { | |||
76 | is_new_item: false, | 78 | is_new_item: false, |
77 | dot_receiver: None, | 79 | dot_receiver: None, |
78 | is_call: false, | 80 | is_call: false, |
81 | is_path_type: false, | ||
82 | has_type_args: false, | ||
79 | }; | 83 | }; |
80 | ctx.fill(&original_parse, position.offset); | 84 | ctx.fill(&original_parse, position.offset); |
81 | Some(ctx) | 85 | Some(ctx) |
@@ -176,6 +180,9 @@ impl<'a> CompletionContext<'a> { | |||
176 | .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) | 180 | .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) |
177 | .is_some(); | 181 | .is_some(); |
178 | 182 | ||
183 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | ||
184 | self.has_type_args = segment.type_arg_list().is_some(); | ||
185 | |||
179 | if let Some(mut path) = hir::Path::from_ast(path.clone()) { | 186 | if let Some(mut path) = hir::Path::from_ast(path.clone()) { |
180 | if !path.is_ident() { | 187 | if !path.is_ident() { |
181 | path.segments.pop().unwrap(); | 188 | path.segments.pop().unwrap(); |
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index eb480a775..400a266a2 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; | 3 | use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | 7 | ||
8 | use crate::completion::{ | 8 | use crate::completion::{ |
9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 9 | db, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::display::{const_label, function_label, macro_label, type_label}; | 12 | use crate::display::{const_label, function_label, macro_label, type_label}; |
@@ -50,14 +50,8 @@ impl Completions { | |||
50 | ScopeDef::ModuleDef(Function(func)) => { | 50 | ScopeDef::ModuleDef(Function(func)) => { |
51 | return self.add_function_with_name(ctx, Some(local_name), *func); | 51 | return self.add_function_with_name(ctx, Some(local_name), *func); |
52 | } | 52 | } |
53 | ScopeDef::ModuleDef(Adt(hir::Adt::Struct(it))) => { | 53 | ScopeDef::ModuleDef(Adt(adt)) => { |
54 | (CompletionItemKind::Struct, it.docs(ctx.db)) | 54 | return self.add_adt_with_name(ctx, local_name, *adt); |
55 | } | ||
56 | ScopeDef::ModuleDef(Adt(hir::Adt::Union(it))) => { | ||
57 | (CompletionItemKind::Struct, it.docs(ctx.db)) | ||
58 | } | ||
59 | ScopeDef::ModuleDef(Adt(hir::Adt::Enum(it))) => { | ||
60 | (CompletionItemKind::Enum, it.docs(ctx.db)) | ||
61 | } | 55 | } |
62 | ScopeDef::ModuleDef(EnumVariant(it)) => { | 56 | ScopeDef::ModuleDef(EnumVariant(it)) => { |
63 | (CompletionItemKind::EnumVariant, it.docs(ctx.db)) | 57 | (CompletionItemKind::EnumVariant, it.docs(ctx.db)) |
@@ -156,7 +150,8 @@ impl Completions { | |||
156 | }) | 150 | }) |
157 | .set_documentation(func.docs(ctx.db)) | 151 | .set_documentation(func.docs(ctx.db)) |
158 | .detail(detail); | 152 | .detail(detail); |
159 | // If not an import, add parenthesis automatically. | 153 | |
154 | // Add `<>` for generic types | ||
160 | if ctx.use_item_syntax.is_none() | 155 | if ctx.use_item_syntax.is_none() |
161 | && !ctx.is_call | 156 | && !ctx.is_call |
162 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | 157 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") |
@@ -170,9 +165,36 @@ impl Completions { | |||
170 | }; | 165 | }; |
171 | builder = builder.insert_snippet(snippet); | 166 | builder = builder.insert_snippet(snippet); |
172 | } | 167 | } |
168 | |||
173 | self.add(builder) | 169 | self.add(builder) |
174 | } | 170 | } |
175 | 171 | ||
172 | fn add_adt_with_name(&mut self, ctx: &CompletionContext, name: String, adt: hir::Adt) { | ||
173 | let mut builder = | ||
174 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()); | ||
175 | |||
176 | let kind = match adt { | ||
177 | hir::Adt::Struct(_) => CompletionItemKind::Struct, | ||
178 | // FIXME: add CompletionItemKind::Union | ||
179 | hir::Adt::Union(_) => CompletionItemKind::Struct, | ||
180 | hir::Adt::Enum(_) => CompletionItemKind::Enum, | ||
181 | }; | ||
182 | let docs = adt.docs(ctx.db); | ||
183 | |||
184 | // If not an import, add parenthesis automatically. | ||
185 | if ctx.is_path_type | ||
186 | && !ctx.has_type_args | ||
187 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | ||
188 | { | ||
189 | if has_non_default_type_params(adt, ctx.db) { | ||
190 | tested_by!(inserts_angle_brackets_for_generics); | ||
191 | builder = builder.insert_snippet(format!("{}<$0>", name)); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | builder.kind(kind).set_documentation(docs).add_to(self) | ||
196 | } | ||
197 | |||
176 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { | 198 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { |
177 | let ast_node = constant.source(ctx.db).ast; | 199 | let ast_node = constant.source(ctx.db).ast; |
178 | let name = match ast_node.name() { | 200 | let name = match ast_node.name() { |
@@ -213,7 +235,6 @@ impl Completions { | |||
213 | .separator(", ") | 235 | .separator(", ") |
214 | .surround_with("(", ")") | 236 | .surround_with("(", ")") |
215 | .to_string(); | 237 | .to_string(); |
216 | |||
217 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) | 238 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) |
218 | .kind(CompletionItemKind::EnumVariant) | 239 | .kind(CompletionItemKind::EnumVariant) |
219 | .set_documentation(variant.docs(ctx.db)) | 240 | .set_documentation(variant.docs(ctx.db)) |
@@ -222,6 +243,11 @@ impl Completions { | |||
222 | } | 243 | } |
223 | } | 244 | } |
224 | 245 | ||
246 | fn has_non_default_type_params(adt: hir::Adt, db: &db::RootDatabase) -> bool { | ||
247 | let subst = db.generic_defaults(adt.into()); | ||
248 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
249 | } | ||
250 | |||
225 | #[cfg(test)] | 251 | #[cfg(test)] |
226 | mod tests { | 252 | mod tests { |
227 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 253 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; |
@@ -389,4 +415,90 @@ mod tests { | |||
389 | ]"# | 415 | ]"# |
390 | ); | 416 | ); |
391 | } | 417 | } |
418 | |||
419 | #[test] | ||
420 | fn inserts_angle_brackets_for_generics() { | ||
421 | covers!(inserts_angle_brackets_for_generics); | ||
422 | assert_debug_snapshot!( | ||
423 | do_reference_completion( | ||
424 | r" | ||
425 | struct Vec<T> {} | ||
426 | fn foo(xs: Ve<|>) | ||
427 | " | ||
428 | ), | ||
429 | @r###" | ||
430 | [ | ||
431 | CompletionItem { | ||
432 | label: "Vec", | ||
433 | source_range: [61; 63), | ||
434 | delete: [61; 63), | ||
435 | insert: "Vec<$0>", | ||
436 | kind: Struct, | ||
437 | }, | ||
438 | CompletionItem { | ||
439 | label: "foo", | ||
440 | source_range: [61; 63), | ||
441 | delete: [61; 63), | ||
442 | insert: "foo($0)", | ||
443 | kind: Function, | ||
444 | detail: "fn foo(xs: Ve)", | ||
445 | }, | ||
446 | ] | ||
447 | "### | ||
448 | ); | ||
449 | assert_debug_snapshot!( | ||
450 | do_reference_completion( | ||
451 | r" | ||
452 | struct Vec<T = i128> {} | ||
453 | fn foo(xs: Ve<|>) | ||
454 | " | ||
455 | ), | ||
456 | @r###" | ||
457 | [ | ||
458 | CompletionItem { | ||
459 | label: "Vec", | ||
460 | source_range: [68; 70), | ||
461 | delete: [68; 70), | ||
462 | insert: "Vec", | ||
463 | kind: Struct, | ||
464 | }, | ||
465 | CompletionItem { | ||
466 | label: "foo", | ||
467 | source_range: [68; 70), | ||
468 | delete: [68; 70), | ||
469 | insert: "foo($0)", | ||
470 | kind: Function, | ||
471 | detail: "fn foo(xs: Ve)", | ||
472 | }, | ||
473 | ] | ||
474 | "### | ||
475 | ); | ||
476 | assert_debug_snapshot!( | ||
477 | do_reference_completion( | ||
478 | r" | ||
479 | struct Vec<T> {} | ||
480 | fn foo(xs: Ve<|><i128>) | ||
481 | " | ||
482 | ), | ||
483 | @r###" | ||
484 | [ | ||
485 | CompletionItem { | ||
486 | label: "Vec", | ||
487 | source_range: [61; 63), | ||
488 | delete: [61; 63), | ||
489 | insert: "Vec", | ||
490 | kind: Struct, | ||
491 | }, | ||
492 | CompletionItem { | ||
493 | label: "foo", | ||
494 | source_range: [61; 63), | ||
495 | delete: [61; 63), | ||
496 | insert: "foo($0)", | ||
497 | kind: Function, | ||
498 | detail: "fn foo(xs: Ve<i128>)", | ||
499 | }, | ||
500 | ] | ||
501 | "### | ||
502 | ); | ||
503 | } | ||
392 | } | 504 | } |
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index 3f4ba248b..848ae4dc7 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! See test_utils/src/marks.rs | 1 | //! See test_utils/src/marks.rs |
2 | 2 | ||
3 | test_utils::marks!( | 3 | test_utils::marks!( |
4 | inserts_angle_brackets_for_generics | ||
4 | inserts_parens_for_function_calls | 5 | inserts_parens_for_function_calls |
5 | goto_definition_works_for_macros | 6 | goto_definition_works_for_macros |
6 | goto_definition_works_for_methods | 7 | goto_definition_works_for_methods |