diff options
Diffstat (limited to 'crates/ide_completion/src')
-rw-r--r-- | crates/ide_completion/src/completions.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/flyimport.rs | 116 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/pattern.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/postfix/format_like.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/qualified_path.rs | 4 | ||||
-rw-r--r-- | crates/ide_completion/src/item.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/lib.rs | 30 |
7 files changed, 153 insertions, 5 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index 6d572a836..e2994eed4 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -220,7 +220,7 @@ fn complete_enum_variants( | |||
220 | }; | 220 | }; |
221 | 221 | ||
222 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { | 222 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { |
223 | if impl_.target_ty(ctx.db) == *ty { | 223 | if impl_.self_ty(ctx.db) == *ty { |
224 | for &variant in &variants { | 224 | for &variant in &variants { |
225 | let self_path = hir::ModPath::from_segments( | 225 | let self_path = hir::ModPath::from_segments( |
226 | hir::PathKind::Plain, | 226 | hir::PathKind::Plain, |
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index 1ad017198..8e211ae1e 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -113,6 +113,9 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) | |||
113 | if ctx.use_item_syntax.is_some() | 113 | if ctx.use_item_syntax.is_some() |
114 | || ctx.attribute_under_caret.is_some() | 114 | || ctx.attribute_under_caret.is_some() |
115 | || ctx.mod_declaration_under_caret.is_some() | 115 | || ctx.mod_declaration_under_caret.is_some() |
116 | || ctx.record_lit_syntax.is_some() | ||
117 | || ctx.has_trait_parent | ||
118 | || ctx.has_impl_parent | ||
116 | { | 119 | { |
117 | return None; | 120 | return None; |
118 | } | 121 | } |
@@ -1034,4 +1037,117 @@ fn main() { | |||
1034 | expect![[]], | 1037 | expect![[]], |
1035 | ); | 1038 | ); |
1036 | } | 1039 | } |
1040 | |||
1041 | #[test] | ||
1042 | fn no_fuzzy_during_fields_of_record_lit_syntax() { | ||
1043 | check( | ||
1044 | r#" | ||
1045 | mod m { | ||
1046 | pub fn some_fn() -> i32 { | ||
1047 | 42 | ||
1048 | } | ||
1049 | } | ||
1050 | struct Foo { | ||
1051 | some_field: i32, | ||
1052 | } | ||
1053 | fn main() { | ||
1054 | let _ = Foo { so$0 }; | ||
1055 | } | ||
1056 | "#, | ||
1057 | expect![[]], | ||
1058 | ); | ||
1059 | } | ||
1060 | |||
1061 | #[test] | ||
1062 | fn fuzzy_after_fields_of_record_lit_syntax() { | ||
1063 | check( | ||
1064 | r#" | ||
1065 | mod m { | ||
1066 | pub fn some_fn() -> i32 { | ||
1067 | 42 | ||
1068 | } | ||
1069 | } | ||
1070 | struct Foo { | ||
1071 | some_field: i32, | ||
1072 | } | ||
1073 | fn main() { | ||
1074 | let _ = Foo { some_field: so$0 }; | ||
1075 | } | ||
1076 | "#, | ||
1077 | expect![[r#" | ||
1078 | fn some_fn() (m::some_fn) fn() -> i32 | ||
1079 | "#]], | ||
1080 | ); | ||
1081 | } | ||
1082 | |||
1083 | #[test] | ||
1084 | fn no_flyimports_in_traits_and_impl_declarations() { | ||
1085 | check( | ||
1086 | r#" | ||
1087 | mod m { | ||
1088 | pub fn some_fn() -> i32 { | ||
1089 | 42 | ||
1090 | } | ||
1091 | } | ||
1092 | trait Foo { | ||
1093 | som$0 | ||
1094 | } | ||
1095 | "#, | ||
1096 | expect![[r#""#]], | ||
1097 | ); | ||
1098 | |||
1099 | check( | ||
1100 | r#" | ||
1101 | mod m { | ||
1102 | pub fn some_fn() -> i32 { | ||
1103 | 42 | ||
1104 | } | ||
1105 | } | ||
1106 | struct Foo; | ||
1107 | impl Foo { | ||
1108 | som$0 | ||
1109 | } | ||
1110 | "#, | ||
1111 | expect![[r#""#]], | ||
1112 | ); | ||
1113 | |||
1114 | check( | ||
1115 | r#" | ||
1116 | mod m { | ||
1117 | pub fn some_fn() -> i32 { | ||
1118 | 42 | ||
1119 | } | ||
1120 | } | ||
1121 | struct Foo; | ||
1122 | trait Bar {} | ||
1123 | impl Bar for Foo { | ||
1124 | som$0 | ||
1125 | } | ||
1126 | "#, | ||
1127 | expect![[r#""#]], | ||
1128 | ); | ||
1129 | } | ||
1130 | |||
1131 | #[test] | ||
1132 | fn no_inherent_candidates_proposed() { | ||
1133 | check( | ||
1134 | r#" | ||
1135 | mod baz { | ||
1136 | pub trait DefDatabase { | ||
1137 | fn method1(&self); | ||
1138 | } | ||
1139 | pub trait HirDatabase: DefDatabase { | ||
1140 | fn method2(&self); | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | mod bar { | ||
1145 | fn test(db: &dyn crate::baz::HirDatabase) { | ||
1146 | db.metho$0 | ||
1147 | } | ||
1148 | } | ||
1149 | "#, | ||
1150 | expect![[r#""#]], | ||
1151 | ); | ||
1152 | } | ||
1037 | } | 1153 | } |
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index b06498e6d..808d7ff7e 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs | |||
@@ -40,7 +40,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
40 | _ => false, | 40 | _ => false, |
41 | }, | 41 | }, |
42 | hir::ScopeDef::MacroDef(_) => true, | 42 | hir::ScopeDef::MacroDef(_) => true, |
43 | hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() { | 43 | hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() { |
44 | Some(hir::Adt::Struct(strukt)) => { | 44 | Some(hir::Adt::Struct(strukt)) => { |
45 | acc.add_struct_pat(ctx, strukt, Some(name.clone())); | 45 | acc.add_struct_pat(ctx, strukt, Some(name.clone())); |
46 | true | 46 | true |
diff --git a/crates/ide_completion/src/completions/postfix/format_like.rs b/crates/ide_completion/src/completions/postfix/format_like.rs index 3f1c6730b..e86ffa8f8 100644 --- a/crates/ide_completion/src/completions/postfix/format_like.rs +++ b/crates/ide_completion/src/completions/postfix/format_like.rs | |||
@@ -13,6 +13,8 @@ | |||
13 | // + `logi` -> `log::info!(...)` | 13 | // + `logi` -> `log::info!(...)` |
14 | // + `logw` -> `log::warn!(...)` | 14 | // + `logw` -> `log::warn!(...)` |
15 | // + `loge` -> `log::error!(...)` | 15 | // + `loge` -> `log::error!(...)` |
16 | // | ||
17 | // image::https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif[] | ||
16 | 18 | ||
17 | use ide_db::helpers::SnippetCap; | 19 | use ide_db::helpers::SnippetCap; |
18 | use syntax::ast::{self, AstToken}; | 20 | use syntax::ast::{self, AstToken}; |
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 105ff6013..969249df6 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -24,7 +24,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | // Add associated types on type parameters and `Self`. | 26 | // Add associated types on type parameters and `Self`. |
27 | resolution.assoc_type_shorthand_candidates(ctx.db, |alias| { | 27 | resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| { |
28 | acc.add_type_alias(ctx, alias); | 28 | acc.add_type_alias(ctx, alias); |
29 | None::<()> | 29 | None::<()> |
30 | }); | 30 | }); |
@@ -117,7 +117,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
117 | if let Some(krate) = ctx.krate { | 117 | if let Some(krate) = ctx.krate { |
118 | let ty = match resolution { | 118 | let ty = match resolution { |
119 | PathResolution::TypeParam(param) => param.ty(ctx.db), | 119 | PathResolution::TypeParam(param) => param.ty(ctx.db), |
120 | PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db), | 120 | PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db), |
121 | _ => return, | 121 | _ => return, |
122 | }; | 122 | }; |
123 | 123 | ||
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index cc4ac9ea2..16991b688 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs | |||
@@ -29,7 +29,7 @@ pub struct CompletionItem { | |||
29 | /// Range of identifier that is being completed. | 29 | /// Range of identifier that is being completed. |
30 | /// | 30 | /// |
31 | /// It should be used primarily for UI, but we also use this to convert | 31 | /// It should be used primarily for UI, but we also use this to convert |
32 | /// genetic TextEdit into LSP's completion edit (see conv.rs). | 32 | /// generic TextEdit into LSP's completion edit (see conv.rs). |
33 | /// | 33 | /// |
34 | /// `source_range` must contain the completion offset. `insert_text` should | 34 | /// `source_range` must contain the completion offset. `insert_text` should |
35 | /// start with what `source_range` points to, or VSCode will filter out the | 35 | /// start with what `source_range` points to, or VSCode will filter out the |
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 5ac1cb48d..6f3d5c5c5 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs | |||
@@ -81,6 +81,8 @@ pub use crate::{ | |||
81 | // And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities. | 81 | // And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities. |
82 | // Those are the additional completion options with automatic `use` import and options from all project importable items, | 82 | // Those are the additional completion options with automatic `use` import and options from all project importable items, |
83 | // fuzzy matched agains the completion imput. | 83 | // fuzzy matched agains the completion imput. |
84 | // | ||
85 | // image::https://user-images.githubusercontent.com/48062697/113020667-b72ab880-917a-11eb-8778-716cf26a0eb3.gif[] | ||
84 | 86 | ||
85 | /// Main entry point for completion. We run completion as a two-phase process. | 87 | /// Main entry point for completion. We run completion as a two-phase process. |
86 | /// | 88 | /// |
@@ -104,6 +106,34 @@ pub use crate::{ | |||
104 | /// `foo` *should* be present among the completion variants. Filtering by | 106 | /// `foo` *should* be present among the completion variants. Filtering by |
105 | /// identifier prefix/fuzzy match should be done higher in the stack, together | 107 | /// identifier prefix/fuzzy match should be done higher in the stack, together |
106 | /// with ordering of completions (currently this is done by the client). | 108 | /// with ordering of completions (currently this is done by the client). |
109 | /// | ||
110 | /// # Hypothetical Completion Problem | ||
111 | /// | ||
112 | /// There's a curious unsolved problem in the current implementation. Often, you | ||
113 | /// want to compute completions on a *slightly different* text document. | ||
114 | /// | ||
115 | /// In the simplest case, when the code looks like `let x = `, you want to | ||
116 | /// insert a fake identifier to get a better syntax tree: `let x = complete_me`. | ||
117 | /// | ||
118 | /// We do this in `CompletionContext`, and it works OK-enough for *syntax* | ||
119 | /// analysis. However, we might want to, eg, ask for the type of `complete_me` | ||
120 | /// variable, and that's where our current infrastructure breaks down. salsa | ||
121 | /// doesn't allow such "phantom" inputs. | ||
122 | /// | ||
123 | /// Another case where this would be instrumental is macro expansion. We want to | ||
124 | /// insert a fake ident and re-expand code. There's `expand_hypothetical` as a | ||
125 | /// work-around for this. | ||
126 | /// | ||
127 | /// A different use-case is completion of injection (examples and links in doc | ||
128 | /// comments). When computing completion for a path in a doc-comment, you want | ||
129 | /// to inject a fake path expression into the item being documented and complete | ||
130 | /// that. | ||
131 | /// | ||
132 | /// IntelliJ has CodeFragment/Context infrastructure for that. You can create a | ||
133 | /// temporary PSI node, and say that the context ("parent") of this node is some | ||
134 | /// existing node. Asking for, eg, type of this `CodeFragment` node works | ||
135 | /// correctly, as the underlying infrastructure makes use of contexts to do | ||
136 | /// analysis. | ||
107 | pub fn completions( | 137 | pub fn completions( |
108 | db: &RootDatabase, | 138 | db: &RootDatabase, |
109 | config: &CompletionConfig, | 139 | config: &CompletionConfig, |