diff options
Diffstat (limited to 'crates/ra_ide')
27 files changed, 835 insertions, 475 deletions
diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml index 6f8107491..f4181c4eb 100644 --- a/crates/ra_ide/Cargo.toml +++ b/crates/ra_ide/Cargo.toml | |||
@@ -17,7 +17,7 @@ indexmap = "1.3.2" | |||
17 | itertools = "0.9.0" | 17 | itertools = "0.9.0" |
18 | log = "0.4.8" | 18 | log = "0.4.8" |
19 | rustc-hash = "1.1.0" | 19 | rustc-hash = "1.1.0" |
20 | rand = { version = "0.7.3", features = ["small_rng"] } | 20 | oorandom = "11.1.2" |
21 | 21 | ||
22 | stdx = { path = "../stdx" } | 22 | stdx = { path = "../stdx" } |
23 | 23 | ||
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs index c28af8ab3..1fcaf4a32 100644 --- a/crates/ra_ide/src/call_hierarchy.rs +++ b/crates/ra_ide/src/call_hierarchy.rs | |||
@@ -59,7 +59,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
59 | if let Some(nav) = syntax.ancestors().find_map(|node| { | 59 | if let Some(nav) = syntax.ancestors().find_map(|node| { |
60 | match_ast! { | 60 | match_ast! { |
61 | match node { | 61 | match node { |
62 | ast::FnDef(it) => { | 62 | ast::Fn(it) => { |
63 | let def = sema.to_def(&it)?; | 63 | let def = sema.to_def(&it)?; |
64 | Some(def.to_nav(sema.db)) | 64 | Some(def.to_nav(sema.db)) |
65 | }, | 65 | }, |
@@ -181,8 +181,8 @@ fn caller() { | |||
181 | call<|>ee(); | 181 | call<|>ee(); |
182 | } | 182 | } |
183 | "#, | 183 | "#, |
184 | "callee FN_DEF FileId(1) 0..14 3..9", | 184 | "callee FN FileId(1) 0..14 3..9", |
185 | &["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"], | 185 | &["caller FN FileId(1) 15..44 18..24 : [33..39]"], |
186 | &[], | 186 | &[], |
187 | ); | 187 | ); |
188 | } | 188 | } |
@@ -197,8 +197,8 @@ fn caller() { | |||
197 | callee(); | 197 | callee(); |
198 | } | 198 | } |
199 | "#, | 199 | "#, |
200 | "callee FN_DEF FileId(1) 0..14 3..9", | 200 | "callee FN FileId(1) 0..14 3..9", |
201 | &["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"], | 201 | &["caller FN FileId(1) 15..44 18..24 : [33..39]"], |
202 | &[], | 202 | &[], |
203 | ); | 203 | ); |
204 | } | 204 | } |
@@ -214,8 +214,8 @@ fn caller() { | |||
214 | callee(); | 214 | callee(); |
215 | } | 215 | } |
216 | "#, | 216 | "#, |
217 | "callee FN_DEF FileId(1) 0..14 3..9", | 217 | "callee FN FileId(1) 0..14 3..9", |
218 | &["caller FN_DEF FileId(1) 15..58 18..24 : [33..39, 47..53]"], | 218 | &["caller FN FileId(1) 15..58 18..24 : [33..39, 47..53]"], |
219 | &[], | 219 | &[], |
220 | ); | 220 | ); |
221 | } | 221 | } |
@@ -234,10 +234,10 @@ fn caller2() { | |||
234 | callee(); | 234 | callee(); |
235 | } | 235 | } |
236 | "#, | 236 | "#, |
237 | "callee FN_DEF FileId(1) 0..14 3..9", | 237 | "callee FN FileId(1) 0..14 3..9", |
238 | &[ | 238 | &[ |
239 | "caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]", | 239 | "caller1 FN FileId(1) 15..45 18..25 : [34..40]", |
240 | "caller2 FN_DEF FileId(1) 47..77 50..57 : [66..72]", | 240 | "caller2 FN FileId(1) 47..77 50..57 : [66..72]", |
241 | ], | 241 | ], |
242 | &[], | 242 | &[], |
243 | ); | 243 | ); |
@@ -263,10 +263,10 @@ mod tests { | |||
263 | } | 263 | } |
264 | } | 264 | } |
265 | "#, | 265 | "#, |
266 | "callee FN_DEF FileId(1) 0..14 3..9", | 266 | "callee FN FileId(1) 0..14 3..9", |
267 | &[ | 267 | &[ |
268 | "caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]", | 268 | "caller1 FN FileId(1) 15..45 18..25 : [34..40]", |
269 | "test_caller FN_DEF FileId(1) 95..149 110..121 : [134..140]", | 269 | "test_caller FN FileId(1) 95..149 110..121 : [134..140]", |
270 | ], | 270 | ], |
271 | &[], | 271 | &[], |
272 | ); | 272 | ); |
@@ -287,8 +287,8 @@ fn caller() { | |||
287 | //- /foo/mod.rs | 287 | //- /foo/mod.rs |
288 | pub fn callee() {} | 288 | pub fn callee() {} |
289 | "#, | 289 | "#, |
290 | "callee FN_DEF FileId(2) 0..18 7..13", | 290 | "callee FN FileId(2) 0..18 7..13", |
291 | &["caller FN_DEF FileId(1) 27..56 30..36 : [45..51]"], | 291 | &["caller FN FileId(1) 27..56 30..36 : [45..51]"], |
292 | &[], | 292 | &[], |
293 | ); | 293 | ); |
294 | } | 294 | } |
@@ -304,9 +304,9 @@ fn call<|>er() { | |||
304 | callee(); | 304 | callee(); |
305 | } | 305 | } |
306 | "#, | 306 | "#, |
307 | "caller FN_DEF FileId(1) 15..58 18..24", | 307 | "caller FN FileId(1) 15..58 18..24", |
308 | &[], | 308 | &[], |
309 | &["callee FN_DEF FileId(1) 0..14 3..9 : [33..39, 47..53]"], | 309 | &["callee FN FileId(1) 0..14 3..9 : [33..39, 47..53]"], |
310 | ); | 310 | ); |
311 | } | 311 | } |
312 | 312 | ||
@@ -325,9 +325,9 @@ fn call<|>er() { | |||
325 | //- /foo/mod.rs | 325 | //- /foo/mod.rs |
326 | pub fn callee() {} | 326 | pub fn callee() {} |
327 | "#, | 327 | "#, |
328 | "caller FN_DEF FileId(1) 27..56 30..36", | 328 | "caller FN FileId(1) 27..56 30..36", |
329 | &[], | 329 | &[], |
330 | &["callee FN_DEF FileId(2) 0..18 7..13 : [45..51]"], | 330 | &["callee FN FileId(2) 0..18 7..13 : [45..51]"], |
331 | ); | 331 | ); |
332 | } | 332 | } |
333 | 333 | ||
@@ -348,9 +348,9 @@ fn caller3() { | |||
348 | 348 | ||
349 | } | 349 | } |
350 | "#, | 350 | "#, |
351 | "caller2 FN_DEF FileId(1) 33..64 36..43", | 351 | "caller2 FN FileId(1) 33..64 36..43", |
352 | &["caller1 FN_DEF FileId(1) 0..31 3..10 : [19..26]"], | 352 | &["caller1 FN FileId(1) 0..31 3..10 : [19..26]"], |
353 | &["caller3 FN_DEF FileId(1) 66..83 69..76 : [52..59]"], | 353 | &["caller3 FN FileId(1) 66..83 69..76 : [52..59]"], |
354 | ); | 354 | ); |
355 | } | 355 | } |
356 | 356 | ||
@@ -368,9 +368,9 @@ fn main() { | |||
368 | a<|>() | 368 | a<|>() |
369 | } | 369 | } |
370 | "#, | 370 | "#, |
371 | "a FN_DEF FileId(1) 0..18 3..4", | 371 | "a FN FileId(1) 0..18 3..4", |
372 | &["main FN_DEF FileId(1) 31..52 34..38 : [47..48]"], | 372 | &["main FN FileId(1) 31..52 34..38 : [47..48]"], |
373 | &["b FN_DEF FileId(1) 20..29 23..24 : [13..14]"], | 373 | &["b FN FileId(1) 20..29 23..24 : [13..14]"], |
374 | ); | 374 | ); |
375 | 375 | ||
376 | check_hierarchy( | 376 | check_hierarchy( |
@@ -385,8 +385,8 @@ fn main() { | |||
385 | a() | 385 | a() |
386 | } | 386 | } |
387 | "#, | 387 | "#, |
388 | "b FN_DEF FileId(1) 20..29 23..24", | 388 | "b FN FileId(1) 20..29 23..24", |
389 | &["a FN_DEF FileId(1) 0..18 3..4 : [13..14]"], | 389 | &["a FN FileId(1) 0..18 3..4 : [13..14]"], |
390 | &[], | 390 | &[], |
391 | ); | 391 | ); |
392 | } | 392 | } |
diff --git a/crates/ra_ide/src/completion/complete_attribute.rs b/crates/ra_ide/src/completion/complete_attribute.rs index d268c92be..2faaae974 100644 --- a/crates/ra_ide/src/completion/complete_attribute.rs +++ b/crates/ra_ide/src/completion/complete_attribute.rs | |||
@@ -13,14 +13,18 @@ use crate::completion::{ | |||
13 | 13 | ||
14 | pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { | 14 | pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { |
15 | let attribute = ctx.attribute_under_caret.as_ref()?; | 15 | let attribute = ctx.attribute_under_caret.as_ref()?; |
16 | 16 | match (attribute.path(), attribute.token_tree()) { | |
17 | match (attribute.path(), attribute.input()) { | 17 | (Some(path), Some(token_tree)) if path.to_string() == "derive" => { |
18 | (Some(path), Some(ast::AttrInput::TokenTree(token_tree))) | ||
19 | if path.to_string() == "derive" => | ||
20 | { | ||
21 | complete_derive(acc, ctx, token_tree) | 18 | complete_derive(acc, ctx, token_tree) |
22 | } | 19 | } |
23 | (_, Some(ast::AttrInput::TokenTree(_token_tree))) => {} | 20 | (Some(path), Some(token_tree)) |
21 | if ["allow", "warn", "deny", "forbid"] | ||
22 | .iter() | ||
23 | .any(|lint_level| lint_level == &path.to_string()) => | ||
24 | { | ||
25 | complete_lint(acc, ctx, token_tree) | ||
26 | } | ||
27 | (_, Some(_token_tree)) => {} | ||
24 | _ => complete_attribute_start(acc, ctx, attribute), | 28 | _ => complete_attribute_start(acc, ctx, attribute), |
25 | } | 29 | } |
26 | Some(()) | 30 | Some(()) |
@@ -125,7 +129,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[ | |||
125 | ]; | 129 | ]; |
126 | 130 | ||
127 | fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { | 131 | fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { |
128 | if let Ok(existing_derives) = parse_derive_input(derive_input) { | 132 | if let Ok(existing_derives) = parse_comma_sep_input(derive_input) { |
129 | for derive_completion in DEFAULT_DERIVE_COMPLETIONS | 133 | for derive_completion in DEFAULT_DERIVE_COMPLETIONS |
130 | .into_iter() | 134 | .into_iter() |
131 | .filter(|completion| !existing_derives.contains(completion.label)) | 135 | .filter(|completion| !existing_derives.contains(completion.label)) |
@@ -158,7 +162,26 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: | |||
158 | } | 162 | } |
159 | } | 163 | } |
160 | 164 | ||
161 | fn parse_derive_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> { | 165 | fn complete_lint(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { |
166 | if let Ok(existing_lints) = parse_comma_sep_input(derive_input) { | ||
167 | for lint_completion in DEFAULT_LINT_COMPLETIONS | ||
168 | .into_iter() | ||
169 | .filter(|completion| !existing_lints.contains(completion.label)) | ||
170 | { | ||
171 | acc.add( | ||
172 | CompletionItem::new( | ||
173 | CompletionKind::Attribute, | ||
174 | ctx.source_range(), | ||
175 | lint_completion.label, | ||
176 | ) | ||
177 | .kind(CompletionItemKind::Attribute) | ||
178 | .detail(lint_completion.description), | ||
179 | ); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> { | ||
162 | match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) { | 185 | match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) { |
163 | (Some(left_paren), Some(right_paren)) | 186 | (Some(left_paren), Some(right_paren)) |
164 | if left_paren.kind() == SyntaxKind::L_PAREN | 187 | if left_paren.kind() == SyntaxKind::L_PAREN |
@@ -212,6 +235,7 @@ struct DeriveCompletion { | |||
212 | 235 | ||
213 | /// Standard Rust derives and the information about their dependencies | 236 | /// Standard Rust derives and the information about their dependencies |
214 | /// (the dependencies are needed so that the main derive don't break the compilation when added) | 237 | /// (the dependencies are needed so that the main derive don't break the compilation when added) |
238 | #[rustfmt::skip] | ||
215 | const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ | 239 | const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ |
216 | DeriveCompletion { label: "Clone", dependencies: &[] }, | 240 | DeriveCompletion { label: "Clone", dependencies: &[] }, |
217 | DeriveCompletion { label: "Copy", dependencies: &["Clone"] }, | 241 | DeriveCompletion { label: "Copy", dependencies: &["Clone"] }, |
@@ -224,6 +248,130 @@ const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ | |||
224 | DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] }, | 248 | DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] }, |
225 | ]; | 249 | ]; |
226 | 250 | ||
251 | struct LintCompletion { | ||
252 | label: &'static str, | ||
253 | description: &'static str, | ||
254 | } | ||
255 | |||
256 | #[rustfmt::skip] | ||
257 | const DEFAULT_LINT_COMPLETIONS: &[LintCompletion] = &[ | ||
258 | LintCompletion { label: "absolute_paths_not_starting_with_crate", description: r#"fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name"# }, | ||
259 | LintCompletion { label: "anonymous_parameters", description: r#"detects anonymous parameters"# }, | ||
260 | LintCompletion { label: "box_pointers", description: r#"use of owned (Box type) heap memory"# }, | ||
261 | LintCompletion { label: "deprecated_in_future", description: r#"detects use of items that will be deprecated in a future version"# }, | ||
262 | LintCompletion { label: "elided_lifetimes_in_paths", description: r#"hidden lifetime parameters in types are deprecated"# }, | ||
263 | LintCompletion { label: "explicit_outlives_requirements", description: r#"outlives requirements can be inferred"# }, | ||
264 | LintCompletion { label: "indirect_structural_match", description: r#"pattern with const indirectly referencing non-structural-match type"# }, | ||
265 | LintCompletion { label: "keyword_idents", description: r#"detects edition keywords being used as an identifier"# }, | ||
266 | LintCompletion { label: "macro_use_extern_crate", description: r#"the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system"# }, | ||
267 | LintCompletion { label: "meta_variable_misuse", description: r#"possible meta-variable misuse at macro definition"# }, | ||
268 | LintCompletion { label: "missing_copy_implementations", description: r#"detects potentially-forgotten implementations of `Copy`"# }, | ||
269 | LintCompletion { label: "missing_crate_level_docs", description: r#"detects crates with no crate-level documentation"# }, | ||
270 | LintCompletion { label: "missing_debug_implementations", description: r#"detects missing implementations of Debug"# }, | ||
271 | LintCompletion { label: "missing_docs", description: r#"detects missing documentation for public members"# }, | ||
272 | LintCompletion { label: "missing_doc_code_examples", description: r#"detects publicly-exported items without code samples in their documentation"# }, | ||
273 | LintCompletion { label: "non_ascii_idents", description: r#"detects non-ASCII identifiers"# }, | ||
274 | LintCompletion { label: "private_doc_tests", description: r#"detects code samples in docs of private items not documented by rustdoc"# }, | ||
275 | LintCompletion { label: "single_use_lifetimes", description: r#"detects lifetime parameters that are only used once"# }, | ||
276 | LintCompletion { label: "trivial_casts", description: r#"detects trivial casts which could be removed"# }, | ||
277 | LintCompletion { label: "trivial_numeric_casts", description: r#"detects trivial casts of numeric types which could be removed"# }, | ||
278 | LintCompletion { label: "unaligned_references", description: r#"detects unaligned references to fields of packed structs"# }, | ||
279 | LintCompletion { label: "unreachable_pub", description: r#"`pub` items not reachable from crate root"# }, | ||
280 | LintCompletion { label: "unsafe_code", description: r#"usage of `unsafe` code"# }, | ||
281 | LintCompletion { label: "unsafe_op_in_unsafe_fn", description: r#"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"# }, | ||
282 | LintCompletion { label: "unstable_features", description: r#"enabling unstable features (deprecated. do not use)"# }, | ||
283 | LintCompletion { label: "unused_crate_dependencies", description: r#"crate dependencies that are never used"# }, | ||
284 | LintCompletion { label: "unused_extern_crates", description: r#"extern crates that are never used"# }, | ||
285 | LintCompletion { label: "unused_import_braces", description: r#"unnecessary braces around an imported item"# }, | ||
286 | LintCompletion { label: "unused_lifetimes", description: r#"detects lifetime parameters that are never used"# }, | ||
287 | LintCompletion { label: "unused_qualifications", description: r#"detects unnecessarily qualified names"# }, | ||
288 | LintCompletion { label: "unused_results", description: r#"unused result of an expression in a statement"# }, | ||
289 | LintCompletion { label: "variant_size_differences", description: r#"detects enums with widely varying variant sizes"# }, | ||
290 | LintCompletion { label: "array_into_iter", description: r#"detects calling `into_iter` on arrays"# }, | ||
291 | LintCompletion { label: "asm_sub_register", description: r#"using only a subset of a register for inline asm inputs"# }, | ||
292 | LintCompletion { label: "bare_trait_objects", description: r#"suggest using `dyn Trait` for trait objects"# }, | ||
293 | LintCompletion { label: "bindings_with_variant_name", description: r#"detects pattern bindings with the same name as one of the matched variants"# }, | ||
294 | LintCompletion { label: "cenum_impl_drop_cast", description: r#"a C-like enum implementing Drop is cast"# }, | ||
295 | LintCompletion { label: "clashing_extern_declarations", description: r#"detects when an extern fn has been declared with the same name but different types"# }, | ||
296 | LintCompletion { label: "coherence_leak_check", description: r#"distinct impls distinguished only by the leak-check code"# }, | ||
297 | LintCompletion { label: "confusable_idents", description: r#"detects visually confusable pairs between identifiers"# }, | ||
298 | LintCompletion { label: "dead_code", description: r#"detect unused, unexported items"# }, | ||
299 | LintCompletion { label: "deprecated", description: r#"detects use of deprecated items"# }, | ||
300 | LintCompletion { label: "ellipsis_inclusive_range_patterns", description: r#"`...` range patterns are deprecated"# }, | ||
301 | LintCompletion { label: "exported_private_dependencies", description: r#"public interface leaks type from a private dependency"# }, | ||
302 | LintCompletion { label: "illegal_floating_point_literal_pattern", description: r#"floating-point literals cannot be used in patterns"# }, | ||
303 | LintCompletion { label: "improper_ctypes", description: r#"proper use of libc types in foreign modules"# }, | ||
304 | LintCompletion { label: "improper_ctypes_definitions", description: r#"proper use of libc types in foreign item definitions"# }, | ||
305 | LintCompletion { label: "incomplete_features", description: r#"incomplete features that may function improperly in some or all cases"# }, | ||
306 | LintCompletion { label: "inline_no_sanitize", description: r#"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"# }, | ||
307 | LintCompletion { label: "intra_doc_link_resolution_failure", description: r#"failures in resolving intra-doc link targets"# }, | ||
308 | LintCompletion { label: "invalid_codeblock_attributes", description: r#"codeblock attribute looks a lot like a known one"# }, | ||
309 | LintCompletion { label: "invalid_value", description: r#"an invalid value is being created (such as a NULL reference)"# }, | ||
310 | LintCompletion { label: "irrefutable_let_patterns", description: r#"detects irrefutable patterns in if-let and while-let statements"# }, | ||
311 | LintCompletion { label: "late_bound_lifetime_arguments", description: r#"detects generic lifetime arguments in path segments with late bound lifetime parameters"# }, | ||
312 | LintCompletion { label: "mixed_script_confusables", description: r#"detects Unicode scripts whose mixed script confusables codepoints are solely used"# }, | ||
313 | LintCompletion { label: "mutable_borrow_reservation_conflict", description: r#"reservation of a two-phased borrow conflicts with other shared borrows"# }, | ||
314 | LintCompletion { label: "non_camel_case_types", description: r#"types, variants, traits and type parameters should have camel case names"# }, | ||
315 | LintCompletion { label: "non_shorthand_field_patterns", description: r#"using `Struct { x: x }` instead of `Struct { x }` in a pattern"# }, | ||
316 | LintCompletion { label: "non_snake_case", description: r#"variables, methods, functions, lifetime parameters and modules should have snake case names"# }, | ||
317 | LintCompletion { label: "non_upper_case_globals", description: r#"static constants should have uppercase identifiers"# }, | ||
318 | LintCompletion { label: "no_mangle_generic_items", description: r#"generic items must be mangled"# }, | ||
319 | LintCompletion { label: "overlapping_patterns", description: r#"detects overlapping patterns"# }, | ||
320 | LintCompletion { label: "path_statements", description: r#"path statements with no effect"# }, | ||
321 | LintCompletion { label: "private_in_public", description: r#"detect private items in public interfaces not caught by the old implementation"# }, | ||
322 | LintCompletion { label: "proc_macro_derive_resolution_fallback", description: r#"detects proc macro derives using inaccessible names from parent modules"# }, | ||
323 | LintCompletion { label: "redundant_semicolons", description: r#"detects unnecessary trailing semicolons"# }, | ||
324 | LintCompletion { label: "renamed_and_removed_lints", description: r#"lints that have been renamed or removed"# }, | ||
325 | LintCompletion { label: "safe_packed_borrows", description: r#"safe borrows of fields of packed structs were erroneously allowed"# }, | ||
326 | LintCompletion { label: "stable_features", description: r#"stable features found in `#[feature]` directive"# }, | ||
327 | LintCompletion { label: "trivial_bounds", description: r#"these bounds don't depend on an type parameters"# }, | ||
328 | LintCompletion { label: "type_alias_bounds", description: r#"bounds in type aliases are not enforced"# }, | ||
329 | LintCompletion { label: "tyvar_behind_raw_pointer", description: r#"raw pointer to an inference variable"# }, | ||
330 | LintCompletion { label: "uncommon_codepoints", description: r#"detects uncommon Unicode codepoints in identifiers"# }, | ||
331 | LintCompletion { label: "unconditional_recursion", description: r#"functions that cannot return without calling themselves"# }, | ||
332 | LintCompletion { label: "unknown_lints", description: r#"unrecognized lint attribute"# }, | ||
333 | LintCompletion { label: "unnameable_test_items", description: r#"detects an item that cannot be named being marked as `#[test_case]`"# }, | ||
334 | LintCompletion { label: "unreachable_code", description: r#"detects unreachable code paths"# }, | ||
335 | LintCompletion { label: "unreachable_patterns", description: r#"detects unreachable patterns"# }, | ||
336 | LintCompletion { label: "unstable_name_collisions", description: r#"detects name collision with an existing but unstable method"# }, | ||
337 | LintCompletion { label: "unused_allocation", description: r#"detects unnecessary allocations that can be eliminated"# }, | ||
338 | LintCompletion { label: "unused_assignments", description: r#"detect assignments that will never be read"# }, | ||
339 | LintCompletion { label: "unused_attributes", description: r#"detects attributes that were not used by the compiler"# }, | ||
340 | LintCompletion { label: "unused_braces", description: r#"unnecessary braces around an expression"# }, | ||
341 | LintCompletion { label: "unused_comparisons", description: r#"comparisons made useless by limits of the types involved"# }, | ||
342 | LintCompletion { label: "unused_doc_comments", description: r#"detects doc comments that aren't used by rustdoc"# }, | ||
343 | LintCompletion { label: "unused_features", description: r#"unused features found in crate-level `#[feature]` directives"# }, | ||
344 | LintCompletion { label: "unused_imports", description: r#"imports that are never used"# }, | ||
345 | LintCompletion { label: "unused_labels", description: r#"detects labels that are never used"# }, | ||
346 | LintCompletion { label: "unused_macros", description: r#"detects macros that were not used"# }, | ||
347 | LintCompletion { label: "unused_must_use", description: r#"unused result of a type flagged as `#[must_use]`"# }, | ||
348 | LintCompletion { label: "unused_mut", description: r#"detect mut variables which don't need to be mutable"# }, | ||
349 | LintCompletion { label: "unused_parens", description: r#"`if`, `match`, `while` and `return` do not need parentheses"# }, | ||
350 | LintCompletion { label: "unused_unsafe", description: r#"unnecessary use of an `unsafe` block"# }, | ||
351 | LintCompletion { label: "unused_variables", description: r#"detect variables which are not used in any way"# }, | ||
352 | LintCompletion { label: "warnings", description: r#"mass-change the level for lints which produce warnings"# }, | ||
353 | LintCompletion { label: "where_clauses_object_safety", description: r#"checks the object safety of where clauses"# }, | ||
354 | LintCompletion { label: "while_true", description: r#"suggest using `loop { }` instead of `while true { }`"# }, | ||
355 | LintCompletion { label: "ambiguous_associated_items", description: r#"ambiguous associated items"# }, | ||
356 | LintCompletion { label: "arithmetic_overflow", description: r#"arithmetic operation overflows"# }, | ||
357 | LintCompletion { label: "conflicting_repr_hints", description: r#"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"# }, | ||
358 | LintCompletion { label: "const_err", description: r#"constant evaluation detected erroneous expression"# }, | ||
359 | LintCompletion { label: "ill_formed_attribute_input", description: r#"ill-formed attribute inputs that were previously accepted and used in practice"# }, | ||
360 | LintCompletion { label: "incomplete_include", description: r#"trailing content in included file"# }, | ||
361 | LintCompletion { label: "invalid_type_param_default", description: r#"type parameter default erroneously allowed in invalid location"# }, | ||
362 | LintCompletion { label: "macro_expanded_macro_exports_accessed_by_absolute_paths", description: r#"macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"# }, | ||
363 | LintCompletion { label: "missing_fragment_specifier", description: r#"detects missing fragment specifiers in unused `macro_rules!` patterns"# }, | ||
364 | LintCompletion { label: "mutable_transmutes", description: r#"mutating transmuted &mut T from &T may cause undefined behavior"# }, | ||
365 | LintCompletion { label: "no_mangle_const_items", description: r#"const items will not have their symbols exported"# }, | ||
366 | LintCompletion { label: "order_dependent_trait_objects", description: r#"trait-object types were treated as different depending on marker-trait order"# }, | ||
367 | LintCompletion { label: "overflowing_literals", description: r#"literal out of range for its type"# }, | ||
368 | LintCompletion { label: "patterns_in_fns_without_body", description: r#"patterns in functions without body were erroneously allowed"# }, | ||
369 | LintCompletion { label: "pub_use_of_private_extern_crate", description: r#"detect public re-exports of private extern crates"# }, | ||
370 | LintCompletion { label: "soft_unstable", description: r#"a feature gate that doesn't break dependent crates"# }, | ||
371 | LintCompletion { label: "unconditional_panic", description: r#"operation will cause a panic at runtime"# }, | ||
372 | LintCompletion { label: "unknown_crate_types", description: r#"unknown crate type found in `#[crate_type]` directive"# }, | ||
373 | ]; | ||
374 | |||
227 | #[cfg(test)] | 375 | #[cfg(test)] |
228 | mod tests { | 376 | mod tests { |
229 | use expect::{expect, Expect}; | 377 | use expect::{expect, Expect}; |
@@ -257,6 +405,130 @@ struct Test {} | |||
257 | } | 405 | } |
258 | 406 | ||
259 | #[test] | 407 | #[test] |
408 | fn empty_lint_completion() { | ||
409 | check( | ||
410 | r#"#[allow(<|>)]"#, | ||
411 | expect![[r#" | ||
412 | at absolute_paths_not_starting_with_crate fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name | ||
413 | at ambiguous_associated_items ambiguous associated items | ||
414 | at anonymous_parameters detects anonymous parameters | ||
415 | at arithmetic_overflow arithmetic operation overflows | ||
416 | at array_into_iter detects calling `into_iter` on arrays | ||
417 | at asm_sub_register using only a subset of a register for inline asm inputs | ||
418 | at bare_trait_objects suggest using `dyn Trait` for trait objects | ||
419 | at bindings_with_variant_name detects pattern bindings with the same name as one of the matched variants | ||
420 | at box_pointers use of owned (Box type) heap memory | ||
421 | at cenum_impl_drop_cast a C-like enum implementing Drop is cast | ||
422 | at clashing_extern_declarations detects when an extern fn has been declared with the same name but different types | ||
423 | at coherence_leak_check distinct impls distinguished only by the leak-check code | ||
424 | at conflicting_repr_hints conflicts between `#[repr(..)]` hints that were previously accepted and used in practice | ||
425 | at confusable_idents detects visually confusable pairs between identifiers | ||
426 | at const_err constant evaluation detected erroneous expression | ||
427 | at dead_code detect unused, unexported items | ||
428 | at deprecated detects use of deprecated items | ||
429 | at deprecated_in_future detects use of items that will be deprecated in a future version | ||
430 | at elided_lifetimes_in_paths hidden lifetime parameters in types are deprecated | ||
431 | at ellipsis_inclusive_range_patterns `...` range patterns are deprecated | ||
432 | at explicit_outlives_requirements outlives requirements can be inferred | ||
433 | at exported_private_dependencies public interface leaks type from a private dependency | ||
434 | at ill_formed_attribute_input ill-formed attribute inputs that were previously accepted and used in practice | ||
435 | at illegal_floating_point_literal_pattern floating-point literals cannot be used in patterns | ||
436 | at improper_ctypes proper use of libc types in foreign modules | ||
437 | at improper_ctypes_definitions proper use of libc types in foreign item definitions | ||
438 | at incomplete_features incomplete features that may function improperly in some or all cases | ||
439 | at incomplete_include trailing content in included file | ||
440 | at indirect_structural_match pattern with const indirectly referencing non-structural-match type | ||
441 | at inline_no_sanitize detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]` | ||
442 | at intra_doc_link_resolution_failure failures in resolving intra-doc link targets | ||
443 | at invalid_codeblock_attributes codeblock attribute looks a lot like a known one | ||
444 | at invalid_type_param_default type parameter default erroneously allowed in invalid location | ||
445 | at invalid_value an invalid value is being created (such as a NULL reference) | ||
446 | at irrefutable_let_patterns detects irrefutable patterns in if-let and while-let statements | ||
447 | at keyword_idents detects edition keywords being used as an identifier | ||
448 | at late_bound_lifetime_arguments detects generic lifetime arguments in path segments with late bound lifetime parameters | ||
449 | at macro_expanded_macro_exports_accessed_by_absolute_paths macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths | ||
450 | at macro_use_extern_crate the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system | ||
451 | at meta_variable_misuse possible meta-variable misuse at macro definition | ||
452 | at missing_copy_implementations detects potentially-forgotten implementations of `Copy` | ||
453 | at missing_crate_level_docs detects crates with no crate-level documentation | ||
454 | at missing_debug_implementations detects missing implementations of Debug | ||
455 | at missing_doc_code_examples detects publicly-exported items without code samples in their documentation | ||
456 | at missing_docs detects missing documentation for public members | ||
457 | at missing_fragment_specifier detects missing fragment specifiers in unused `macro_rules!` patterns | ||
458 | at mixed_script_confusables detects Unicode scripts whose mixed script confusables codepoints are solely used | ||
459 | at mutable_borrow_reservation_conflict reservation of a two-phased borrow conflicts with other shared borrows | ||
460 | at mutable_transmutes mutating transmuted &mut T from &T may cause undefined behavior | ||
461 | at no_mangle_const_items const items will not have their symbols exported | ||
462 | at no_mangle_generic_items generic items must be mangled | ||
463 | at non_ascii_idents detects non-ASCII identifiers | ||
464 | at non_camel_case_types types, variants, traits and type parameters should have camel case names | ||
465 | at non_shorthand_field_patterns using `Struct { x: x }` instead of `Struct { x }` in a pattern | ||
466 | at non_snake_case variables, methods, functions, lifetime parameters and modules should have snake case names | ||
467 | at non_upper_case_globals static constants should have uppercase identifiers | ||
468 | at order_dependent_trait_objects trait-object types were treated as different depending on marker-trait order | ||
469 | at overflowing_literals literal out of range for its type | ||
470 | at overlapping_patterns detects overlapping patterns | ||
471 | at path_statements path statements with no effect | ||
472 | at patterns_in_fns_without_body patterns in functions without body were erroneously allowed | ||
473 | at private_doc_tests detects code samples in docs of private items not documented by rustdoc | ||
474 | at private_in_public detect private items in public interfaces not caught by the old implementation | ||
475 | at proc_macro_derive_resolution_fallback detects proc macro derives using inaccessible names from parent modules | ||
476 | at pub_use_of_private_extern_crate detect public re-exports of private extern crates | ||
477 | at redundant_semicolons detects unnecessary trailing semicolons | ||
478 | at renamed_and_removed_lints lints that have been renamed or removed | ||
479 | at safe_packed_borrows safe borrows of fields of packed structs were erroneously allowed | ||
480 | at single_use_lifetimes detects lifetime parameters that are only used once | ||
481 | at soft_unstable a feature gate that doesn't break dependent crates | ||
482 | at stable_features stable features found in `#[feature]` directive | ||
483 | at trivial_bounds these bounds don't depend on an type parameters | ||
484 | at trivial_casts detects trivial casts which could be removed | ||
485 | at trivial_numeric_casts detects trivial casts of numeric types which could be removed | ||
486 | at type_alias_bounds bounds in type aliases are not enforced | ||
487 | at tyvar_behind_raw_pointer raw pointer to an inference variable | ||
488 | at unaligned_references detects unaligned references to fields of packed structs | ||
489 | at uncommon_codepoints detects uncommon Unicode codepoints in identifiers | ||
490 | at unconditional_panic operation will cause a panic at runtime | ||
491 | at unconditional_recursion functions that cannot return without calling themselves | ||
492 | at unknown_crate_types unknown crate type found in `#[crate_type]` directive | ||
493 | at unknown_lints unrecognized lint attribute | ||
494 | at unnameable_test_items detects an item that cannot be named being marked as `#[test_case]` | ||
495 | at unreachable_code detects unreachable code paths | ||
496 | at unreachable_patterns detects unreachable patterns | ||
497 | at unreachable_pub `pub` items not reachable from crate root | ||
498 | at unsafe_code usage of `unsafe` code | ||
499 | at unsafe_op_in_unsafe_fn unsafe operations in unsafe functions without an explicit unsafe block are deprecated | ||
500 | at unstable_features enabling unstable features (deprecated. do not use) | ||
501 | at unstable_name_collisions detects name collision with an existing but unstable method | ||
502 | at unused_allocation detects unnecessary allocations that can be eliminated | ||
503 | at unused_assignments detect assignments that will never be read | ||
504 | at unused_attributes detects attributes that were not used by the compiler | ||
505 | at unused_braces unnecessary braces around an expression | ||
506 | at unused_comparisons comparisons made useless by limits of the types involved | ||
507 | at unused_crate_dependencies crate dependencies that are never used | ||
508 | at unused_doc_comments detects doc comments that aren't used by rustdoc | ||
509 | at unused_extern_crates extern crates that are never used | ||
510 | at unused_features unused features found in crate-level `#[feature]` directives | ||
511 | at unused_import_braces unnecessary braces around an imported item | ||
512 | at unused_imports imports that are never used | ||
513 | at unused_labels detects labels that are never used | ||
514 | at unused_lifetimes detects lifetime parameters that are never used | ||
515 | at unused_macros detects macros that were not used | ||
516 | at unused_must_use unused result of a type flagged as `#[must_use]` | ||
517 | at unused_mut detect mut variables which don't need to be mutable | ||
518 | at unused_parens `if`, `match`, `while` and `return` do not need parentheses | ||
519 | at unused_qualifications detects unnecessarily qualified names | ||
520 | at unused_results unused result of an expression in a statement | ||
521 | at unused_unsafe unnecessary use of an `unsafe` block | ||
522 | at unused_variables detect variables which are not used in any way | ||
523 | at variant_size_differences detects enums with widely varying variant sizes | ||
524 | at warnings mass-change the level for lints which produce warnings | ||
525 | at where_clauses_object_safety checks the object safety of where clauses | ||
526 | at while_true suggest using `loop { }` instead of `while true { }` | ||
527 | "#]], | ||
528 | ) | ||
529 | } | ||
530 | |||
531 | #[test] | ||
260 | fn no_completion_for_incorrect_derive() { | 532 | fn no_completion_for_incorrect_derive() { |
261 | check( | 533 | check( |
262 | r#" | 534 | r#" |
@@ -325,7 +597,7 @@ struct Test {} | |||
325 | 597 | ||
326 | #[test] | 598 | #[test] |
327 | fn test_attribute_completion_inside_nested_attr() { | 599 | fn test_attribute_completion_inside_nested_attr() { |
328 | check(r#"#[allow(<|>)]"#, expect![[]]) | 600 | check(r#"#[cfg(<|>)]"#, expect![[]]) |
329 | } | 601 | } |
330 | 602 | ||
331 | #[test] | 603 | #[test] |
diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs index db2abb4f1..406334257 100644 --- a/crates/ra_ide/src/completion/complete_fn_param.rs +++ b/crates/ra_ide/src/completion/complete_fn_param.rs | |||
@@ -18,26 +18,36 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
18 | } | 18 | } |
19 | 19 | ||
20 | let mut params = FxHashMap::default(); | 20 | let mut params = FxHashMap::default(); |
21 | let me = ctx.token.ancestors().find_map(ast::FnDef::cast); | 21 | |
22 | let me = ctx.token.ancestors().find_map(ast::Fn::cast); | ||
23 | let mut process_fn = |func: ast::Fn| { | ||
24 | if Some(&func) == me.as_ref() { | ||
25 | return; | ||
26 | } | ||
27 | func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| { | ||
28 | let text = param.syntax().text().to_string(); | ||
29 | params.entry(text).or_insert(param); | ||
30 | }) | ||
31 | }; | ||
32 | |||
22 | for node in ctx.token.parent().ancestors() { | 33 | for node in ctx.token.parent().ancestors() { |
23 | let items = match_ast! { | 34 | match_ast! { |
24 | match node { | 35 | match node { |
25 | ast::SourceFile(it) => it.items(), | 36 | ast::SourceFile(it) => it.items().filter_map(|item| match item { |
26 | ast::ItemList(it) => it.items(), | 37 | ast::Item::Fn(it) => Some(it), |
38 | _ => None, | ||
39 | }).for_each(&mut process_fn), | ||
40 | ast::ItemList(it) => it.items().filter_map(|item| match item { | ||
41 | ast::Item::Fn(it) => Some(it), | ||
42 | _ => None, | ||
43 | }).for_each(&mut process_fn), | ||
44 | ast::AssocItemList(it) => it.assoc_items().filter_map(|item| match item { | ||
45 | ast::AssocItem::Fn(it) => Some(it), | ||
46 | _ => None, | ||
47 | }).for_each(&mut process_fn), | ||
27 | _ => continue, | 48 | _ => continue, |
28 | } | 49 | } |
29 | }; | 50 | }; |
30 | for item in items { | ||
31 | if let ast::ModuleItem::FnDef(func) = item { | ||
32 | if Some(&func) == me.as_ref() { | ||
33 | continue; | ||
34 | } | ||
35 | func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| { | ||
36 | let text = param.syntax().text().to_string(); | ||
37 | params.entry(text).or_insert(param); | ||
38 | }) | ||
39 | } | ||
40 | } | ||
41 | } | 51 | } |
42 | 52 | ||
43 | params | 53 | params |
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index fcdaeef49..b62064797 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -66,27 +66,24 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
66 | add_keyword(ctx, acc, "fn", "fn $0() {}") | 66 | add_keyword(ctx, acc, "fn", "fn $0() {}") |
67 | } | 67 | } |
68 | 68 | ||
69 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 69 | if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent { |
70 | || ctx.block_expr_parent | ||
71 | { | ||
72 | add_keyword(ctx, acc, "trait", "trait $0 {}"); | 70 | add_keyword(ctx, acc, "trait", "trait $0 {}"); |
73 | add_keyword(ctx, acc, "impl", "impl $0 {}"); | 71 | add_keyword(ctx, acc, "impl", "impl $0 {}"); |
74 | } | 72 | } |
75 | 73 | ||
76 | return; | 74 | return; |
77 | } | 75 | } |
78 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { | 76 | if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent |
77 | { | ||
79 | add_keyword(ctx, acc, "fn", "fn $0() {}"); | 78 | add_keyword(ctx, acc, "fn", "fn $0() {}"); |
80 | } | 79 | } |
81 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 80 | if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent { |
82 | || ctx.block_expr_parent | ||
83 | { | ||
84 | add_keyword(ctx, acc, "use", "use "); | 81 | add_keyword(ctx, acc, "use", "use "); |
85 | add_keyword(ctx, acc, "impl", "impl $0 {}"); | 82 | add_keyword(ctx, acc, "impl", "impl $0 {}"); |
86 | add_keyword(ctx, acc, "trait", "trait $0 {}"); | 83 | add_keyword(ctx, acc, "trait", "trait $0 {}"); |
87 | } | 84 | } |
88 | 85 | ||
89 | if ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent { | 86 | if ctx.has_item_list_or_source_file_parent { |
90 | add_keyword(ctx, acc, "enum", "enum $0 {}"); | 87 | add_keyword(ctx, acc, "enum", "enum $0 {}"); |
91 | add_keyword(ctx, acc, "struct", "struct $0"); | 88 | add_keyword(ctx, acc, "struct", "struct $0"); |
92 | add_keyword(ctx, acc, "union", "union $0 {}"); | 89 | add_keyword(ctx, acc, "union", "union $0 {}"); |
@@ -108,29 +105,28 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
108 | add_keyword(ctx, acc, "else", "else {$0}"); | 105 | add_keyword(ctx, acc, "else", "else {$0}"); |
109 | add_keyword(ctx, acc, "else if", "else if $0 {}"); | 106 | add_keyword(ctx, acc, "else if", "else if $0 {}"); |
110 | } | 107 | } |
111 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 108 | if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent { |
112 | || ctx.block_expr_parent | ||
113 | { | ||
114 | add_keyword(ctx, acc, "mod", "mod $0 {}"); | 109 | add_keyword(ctx, acc, "mod", "mod $0 {}"); |
115 | } | 110 | } |
116 | if ctx.bind_pat_parent || ctx.ref_pat_parent { | 111 | if ctx.bind_pat_parent || ctx.ref_pat_parent { |
117 | add_keyword(ctx, acc, "mut", "mut "); | 112 | add_keyword(ctx, acc, "mut", "mut "); |
118 | } | 113 | } |
119 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { | 114 | if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent |
115 | { | ||
120 | add_keyword(ctx, acc, "const", "const "); | 116 | add_keyword(ctx, acc, "const", "const "); |
121 | add_keyword(ctx, acc, "type", "type "); | 117 | add_keyword(ctx, acc, "type", "type "); |
122 | } | 118 | } |
123 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 119 | if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent { |
124 | || ctx.block_expr_parent | ||
125 | { | ||
126 | add_keyword(ctx, acc, "static", "static "); | 120 | add_keyword(ctx, acc, "static", "static "); |
127 | }; | 121 | }; |
128 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 122 | if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent { |
129 | || ctx.block_expr_parent | ||
130 | { | ||
131 | add_keyword(ctx, acc, "extern", "extern "); | 123 | add_keyword(ctx, acc, "extern", "extern "); |
132 | } | 124 | } |
133 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm { | 125 | if ctx.has_item_list_or_source_file_parent |
126 | || has_trait_or_impl_parent | ||
127 | || ctx.block_expr_parent | ||
128 | || ctx.is_match_arm | ||
129 | { | ||
134 | add_keyword(ctx, acc, "unsafe", "unsafe "); | 130 | add_keyword(ctx, acc, "unsafe", "unsafe "); |
135 | } | 131 | } |
136 | if ctx.in_loop_body { | 132 | if ctx.in_loop_body { |
@@ -142,7 +138,7 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
142 | add_keyword(ctx, acc, "break", "break"); | 138 | add_keyword(ctx, acc, "break", "break"); |
143 | } | 139 | } |
144 | } | 140 | } |
145 | if ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent { | 141 | if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent { |
146 | add_keyword(ctx, acc, "pub", "pub ") | 142 | add_keyword(ctx, acc, "pub", "pub ") |
147 | } | 143 | } |
148 | 144 | ||
@@ -173,7 +169,7 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet | |||
173 | 169 | ||
174 | fn complete_return( | 170 | fn complete_return( |
175 | ctx: &CompletionContext, | 171 | ctx: &CompletionContext, |
176 | fn_def: &ast::FnDef, | 172 | fn_def: &ast::Fn, |
177 | can_be_stmt: bool, | 173 | can_be_stmt: bool, |
178 | ) -> Option<CompletionItem> { | 174 | ) -> Option<CompletionItem> { |
179 | let snip = match (can_be_stmt, fn_def.ret_type().is_some()) { | 175 | let snip = match (can_be_stmt, fn_def.ret_type().is_some()) { |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index cf716540f..d9a0ef167 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -2,8 +2,8 @@ | |||
2 | //! | 2 | //! |
3 | //! This module adds the completion items related to implementing associated | 3 | //! This module adds the completion items related to implementing associated |
4 | //! items within a `impl Trait for Struct` block. The current context node | 4 | //! items within a `impl Trait for Struct` block. The current context node |
5 | //! must be within either a `FN_DEF`, `TYPE_ALIAS_DEF`, or `CONST_DEF` node | 5 | //! must be within either a `FN`, `TYPE_ALIAS`, or `CONST` node |
6 | //! and an direct child of an `IMPL_DEF`. | 6 | //! and an direct child of an `IMPL`. |
7 | //! | 7 | //! |
8 | //! # Examples | 8 | //! # Examples |
9 | //! | 9 | //! |
@@ -34,7 +34,7 @@ | |||
34 | use hir::{self, Docs, HasSource}; | 34 | use hir::{self, Docs, HasSource}; |
35 | use ra_assists::utils::get_missing_assoc_items; | 35 | use ra_assists::utils::get_missing_assoc_items; |
36 | use ra_syntax::{ | 36 | use ra_syntax::{ |
37 | ast::{self, edit, ImplDef}, | 37 | ast::{self, edit, Impl}, |
38 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, | 38 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, |
39 | }; | 39 | }; |
40 | use ra_text_edit::TextEdit; | 40 | use ra_text_edit::TextEdit; |
@@ -63,7 +63,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
63 | } | 63 | } |
64 | }), | 64 | }), |
65 | 65 | ||
66 | SyntaxKind::FN_DEF => { | 66 | SyntaxKind::FN => { |
67 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) | 67 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) |
68 | .into_iter() | 68 | .into_iter() |
69 | .filter_map(|item| match item { | 69 | .filter_map(|item| match item { |
@@ -75,7 +75,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | SyntaxKind::TYPE_ALIAS_DEF => { | 78 | SyntaxKind::TYPE_ALIAS => { |
79 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) | 79 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) |
80 | .into_iter() | 80 | .into_iter() |
81 | .filter_map(|item| match item { | 81 | .filter_map(|item| match item { |
@@ -87,7 +87,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
90 | SyntaxKind::CONST_DEF => { | 90 | SyntaxKind::CONST => { |
91 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) | 91 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) |
92 | .into_iter() | 92 | .into_iter() |
93 | .filter_map(|item| match item { | 93 | .filter_map(|item| match item { |
@@ -104,18 +104,17 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
104 | } | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> { | 107 | fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, Impl)> { |
108 | let (trigger, impl_def_offset) = ctx.token.ancestors().find_map(|p| match p.kind() { | 108 | let (trigger, impl_def_offset) = ctx.token.ancestors().find_map(|p| match p.kind() { |
109 | SyntaxKind::FN_DEF | 109 | SyntaxKind::FN | SyntaxKind::TYPE_ALIAS | SyntaxKind::CONST | SyntaxKind::BLOCK_EXPR => { |
110 | | SyntaxKind::TYPE_ALIAS_DEF | 110 | Some((p, 2)) |
111 | | SyntaxKind::CONST_DEF | 111 | } |
112 | | SyntaxKind::BLOCK_EXPR => Some((p, 2)), | ||
113 | SyntaxKind::NAME_REF => Some((p, 5)), | 112 | SyntaxKind::NAME_REF => Some((p, 5)), |
114 | _ => None, | 113 | _ => None, |
115 | })?; | 114 | })?; |
116 | let impl_def = (0..impl_def_offset - 1) | 115 | let impl_def = (0..impl_def_offset - 1) |
117 | .try_fold(trigger.parent()?, |t, _| t.parent()) | 116 | .try_fold(trigger.parent()?, |t, _| t.parent()) |
118 | .and_then(ast::ImplDef::cast)?; | 117 | .and_then(ast::Impl::cast)?; |
119 | Some((trigger, impl_def)) | 118 | Some((trigger, impl_def)) |
120 | } | 119 | } |
121 | 120 | ||
@@ -201,7 +200,7 @@ fn add_const_impl( | |||
201 | } | 200 | } |
202 | } | 201 | } |
203 | 202 | ||
204 | fn make_const_compl_syntax(const_: &ast::ConstDef) -> String { | 203 | fn make_const_compl_syntax(const_: &ast::Const) -> String { |
205 | let const_ = edit::remove_attrs_and_docs(const_); | 204 | let const_ = edit::remove_attrs_and_docs(const_); |
206 | 205 | ||
207 | let const_start = const_.syntax().text_range().start(); | 206 | let const_start = const_.syntax().text_range().start(); |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index c84d43d77..2113abbb2 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -35,12 +35,12 @@ pub(crate) struct CompletionContext<'a> { | |||
35 | pub(super) krate: Option<hir::Crate>, | 35 | pub(super) krate: Option<hir::Crate>, |
36 | pub(super) expected_type: Option<Type>, | 36 | pub(super) expected_type: Option<Type>, |
37 | pub(super) name_ref_syntax: Option<ast::NameRef>, | 37 | pub(super) name_ref_syntax: Option<ast::NameRef>, |
38 | pub(super) function_syntax: Option<ast::FnDef>, | 38 | pub(super) function_syntax: Option<ast::Fn>, |
39 | pub(super) use_item_syntax: Option<ast::UseItem>, | 39 | pub(super) use_item_syntax: Option<ast::Use>, |
40 | pub(super) record_lit_syntax: Option<ast::RecordLit>, | 40 | pub(super) record_lit_syntax: Option<ast::RecordExpr>, |
41 | pub(super) record_pat_syntax: Option<ast::RecordPat>, | 41 | pub(super) record_pat_syntax: Option<ast::RecordPat>, |
42 | pub(super) record_field_syntax: Option<ast::RecordField>, | 42 | pub(super) record_field_syntax: Option<ast::RecordExprField>, |
43 | pub(super) impl_def: Option<ast::ImplDef>, | 43 | pub(super) impl_def: Option<ast::Impl>, |
44 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong | 44 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong |
45 | pub(super) active_parameter: Option<ActiveParameter>, | 45 | pub(super) active_parameter: Option<ActiveParameter>, |
46 | pub(super) is_param: bool, | 46 | pub(super) is_param: bool, |
@@ -316,7 +316,7 @@ impl<'a> CompletionContext<'a> { | |||
316 | self.name_ref_syntax = | 316 | self.name_ref_syntax = |
317 | find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); | 317 | find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); |
318 | let name_range = name_ref.syntax().text_range(); | 318 | let name_range = name_ref.syntax().text_range(); |
319 | if ast::RecordField::for_field_name(&name_ref).is_some() { | 319 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { |
320 | self.record_lit_syntax = | 320 | self.record_lit_syntax = |
321 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | 321 | self.sema.find_node_at_offset_with_macros(&original_file, offset); |
322 | } | 322 | } |
@@ -325,7 +325,7 @@ impl<'a> CompletionContext<'a> { | |||
325 | .sema | 325 | .sema |
326 | .ancestors_with_macros(self.token.parent()) | 326 | .ancestors_with_macros(self.token.parent()) |
327 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) | 327 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) |
328 | .find_map(ast::ImplDef::cast); | 328 | .find_map(ast::Impl::cast); |
329 | 329 | ||
330 | let top_node = name_ref | 330 | let top_node = name_ref |
331 | .syntax() | 331 | .syntax() |
@@ -343,13 +343,13 @@ impl<'a> CompletionContext<'a> { | |||
343 | } | 343 | } |
344 | 344 | ||
345 | self.use_item_syntax = | 345 | self.use_item_syntax = |
346 | self.sema.ancestors_with_macros(self.token.parent()).find_map(ast::UseItem::cast); | 346 | self.sema.ancestors_with_macros(self.token.parent()).find_map(ast::Use::cast); |
347 | 347 | ||
348 | self.function_syntax = self | 348 | self.function_syntax = self |
349 | .sema | 349 | .sema |
350 | .ancestors_with_macros(self.token.parent()) | 350 | .ancestors_with_macros(self.token.parent()) |
351 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) | 351 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) |
352 | .find_map(ast::FnDef::cast); | 352 | .find_map(ast::Fn::cast); |
353 | 353 | ||
354 | self.record_field_syntax = self | 354 | self.record_field_syntax = self |
355 | .sema | 355 | .sema |
@@ -357,7 +357,7 @@ impl<'a> CompletionContext<'a> { | |||
357 | .take_while(|it| { | 357 | .take_while(|it| { |
358 | it.kind() != SOURCE_FILE && it.kind() != MODULE && it.kind() != CALL_EXPR | 358 | it.kind() != SOURCE_FILE && it.kind() != MODULE && it.kind() != CALL_EXPR |
359 | }) | 359 | }) |
360 | .find_map(ast::RecordField::cast); | 360 | .find_map(ast::RecordExprField::cast); |
361 | 361 | ||
362 | let parent = match name_ref.syntax().parent() { | 362 | let parent = match name_ref.syntax().parent() { |
363 | Some(it) => it, | 363 | Some(it) => it, |
diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs index b2fe13280..a68861e1c 100644 --- a/crates/ra_ide/src/completion/patterns.rs +++ b/crates/ra_ide/src/completion/patterns.rs | |||
@@ -13,9 +13,9 @@ use crate::completion::test_utils::check_pattern_is_applicable; | |||
13 | 13 | ||
14 | pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { | 14 | pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { |
15 | not_same_range_ancestor(element) | 15 | not_same_range_ancestor(element) |
16 | .filter(|it| it.kind() == ITEM_LIST) | 16 | .filter(|it| it.kind() == ASSOC_ITEM_LIST) |
17 | .and_then(|it| it.parent()) | 17 | .and_then(|it| it.parent()) |
18 | .filter(|it| it.kind() == TRAIT_DEF) | 18 | .filter(|it| it.kind() == TRAIT) |
19 | .is_some() | 19 | .is_some() |
20 | } | 20 | } |
21 | #[test] | 21 | #[test] |
@@ -25,9 +25,9 @@ fn test_has_trait_parent() { | |||
25 | 25 | ||
26 | pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { | 26 | pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { |
27 | not_same_range_ancestor(element) | 27 | not_same_range_ancestor(element) |
28 | .filter(|it| it.kind() == ITEM_LIST) | 28 | .filter(|it| it.kind() == ASSOC_ITEM_LIST) |
29 | .and_then(|it| it.parent()) | 29 | .and_then(|it| it.parent()) |
30 | .filter(|it| it.kind() == IMPL_DEF) | 30 | .filter(|it| it.kind() == IMPL) |
31 | .is_some() | 31 | .is_some() |
32 | } | 32 | } |
33 | #[test] | 33 | #[test] |
@@ -73,7 +73,7 @@ pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> boo | |||
73 | #[test] | 73 | #[test] |
74 | fn test_has_item_list_or_source_file_parent() { | 74 | fn test_has_item_list_or_source_file_parent() { |
75 | check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); | 75 | check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); |
76 | check_pattern_is_applicable(r"impl { f<|> }", has_item_list_or_source_file_parent); | 76 | check_pattern_is_applicable(r"mod foo { f<|> }", has_item_list_or_source_file_parent); |
77 | } | 77 | } |
78 | 78 | ||
79 | pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { | 79 | pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { |
@@ -113,7 +113,7 @@ fn test_if_is_prev() { | |||
113 | } | 113 | } |
114 | 114 | ||
115 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { | 115 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { |
116 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT_DEF).is_some() | 116 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT).is_some() |
117 | } | 117 | } |
118 | #[test] | 118 | #[test] |
119 | fn test_has_trait_as_prev_sibling() { | 119 | fn test_has_trait_as_prev_sibling() { |
@@ -121,7 +121,7 @@ fn test_has_trait_as_prev_sibling() { | |||
121 | } | 121 | } |
122 | 122 | ||
123 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { | 123 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { |
124 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL_DEF).is_some() | 124 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL).is_some() |
125 | } | 125 | } |
126 | #[test] | 126 | #[test] |
127 | fn test_has_impl_as_prev_sibling() { | 127 | fn test_has_impl_as_prev_sibling() { |
@@ -134,7 +134,7 @@ pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { | |||
134 | NodeOrToken::Token(token) => token.parent(), | 134 | NodeOrToken::Token(token) => token.parent(), |
135 | }; | 135 | }; |
136 | for node in leaf.ancestors() { | 136 | for node in leaf.ancestors() { |
137 | if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR { | 137 | if node.kind() == FN || node.kind() == LAMBDA_EXPR { |
138 | break; | 138 | break; |
139 | } | 139 | } |
140 | let loop_body = match_ast! { | 140 | let loop_body = match_ast! { |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index e029af0dc..dd8a7ffd9 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | use std::cell::RefCell; | 7 | use std::cell::RefCell; |
8 | 8 | ||
9 | use hir::{ | 9 | use hir::{ |
10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}, | 10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSinkBuilder}, |
11 | HasSource, HirDisplay, Semantics, VariantDef, | 11 | HasSource, HirDisplay, Semantics, VariantDef, |
12 | }; | 12 | }; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
@@ -29,7 +29,11 @@ pub enum Severity { | |||
29 | WeakWarning, | 29 | WeakWarning, |
30 | } | 30 | } |
31 | 31 | ||
32 | pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> { | 32 | pub(crate) fn diagnostics( |
33 | db: &RootDatabase, | ||
34 | file_id: FileId, | ||
35 | enable_experimental: bool, | ||
36 | ) -> Vec<Diagnostic> { | ||
33 | let _p = profile("diagnostics"); | 37 | let _p = profile("diagnostics"); |
34 | let sema = Semantics::new(db); | 38 | let sema = Semantics::new(db); |
35 | let parse = db.parse(file_id); | 39 | let parse = db.parse(file_id); |
@@ -48,79 +52,85 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
48 | check_struct_shorthand_initialization(&mut res, file_id, &node); | 52 | check_struct_shorthand_initialization(&mut res, file_id, &node); |
49 | } | 53 | } |
50 | let res = RefCell::new(res); | 54 | let res = RefCell::new(res); |
51 | let mut sink = DiagnosticSink::new(|d| { | 55 | let mut sink = DiagnosticSinkBuilder::new() |
52 | res.borrow_mut().push(Diagnostic { | 56 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
53 | message: d.message(), | 57 | let original_file = d.source().file_id.original_file(db); |
54 | range: sema.diagnostics_range(d).range, | 58 | let fix = Fix::new( |
55 | severity: Severity::Error, | 59 | "Create module", |
56 | fix: None, | 60 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() } |
57 | }) | 61 | .into(), |
58 | }) | 62 | ); |
59 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 63 | res.borrow_mut().push(Diagnostic { |
60 | let original_file = d.source().file_id.original_file(db); | 64 | range: sema.diagnostics_range(d).range, |
61 | let fix = Fix::new( | 65 | message: d.message(), |
62 | "Create module", | 66 | severity: Severity::Error, |
63 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() }.into(), | 67 | fix: Some(fix), |
64 | ); | 68 | }) |
65 | res.borrow_mut().push(Diagnostic { | ||
66 | range: sema.diagnostics_range(d).range, | ||
67 | message: d.message(), | ||
68 | severity: Severity::Error, | ||
69 | fix: Some(fix), | ||
70 | }) | 69 | }) |
71 | }) | 70 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
72 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 71 | // Note that although we could add a diagnostics to |
73 | // Note that although we could add a diagnostics to | 72 | // fill the missing tuple field, e.g : |
74 | // fill the missing tuple field, e.g : | 73 | // `struct A(usize);` |
75 | // `struct A(usize);` | 74 | // `let a = A { 0: () }` |
76 | // `let a = A { 0: () }` | 75 | // but it is uncommon usage and it should not be encouraged. |
77 | // but it is uncommon usage and it should not be encouraged. | 76 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { |
78 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { | 77 | None |
79 | None | 78 | } else { |
80 | } else { | 79 | let mut field_list = d.ast(db); |
81 | let mut field_list = d.ast(db); | 80 | for f in d.missed_fields.iter() { |
82 | for f in d.missed_fields.iter() { | 81 | let field = |
83 | let field = | 82 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); |
84 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); | 83 | field_list = field_list.append_field(&field); |
85 | field_list = field_list.append_field(&field); | 84 | } |
86 | } | 85 | |
87 | 86 | let edit = { | |
88 | let edit = { | 87 | let mut builder = TextEditBuilder::default(); |
89 | let mut builder = TextEditBuilder::default(); | 88 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()) |
90 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); | 89 | .into_text_edit(&mut builder); |
91 | builder.finish() | 90 | builder.finish() |
91 | }; | ||
92 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) | ||
92 | }; | 93 | }; |
93 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) | ||
94 | }; | ||
95 | 94 | ||
96 | res.borrow_mut().push(Diagnostic { | 95 | res.borrow_mut().push(Diagnostic { |
97 | range: sema.diagnostics_range(d).range, | 96 | range: sema.diagnostics_range(d).range, |
98 | message: d.message(), | 97 | message: d.message(), |
99 | severity: Severity::Error, | 98 | severity: Severity::Error, |
100 | fix, | 99 | fix, |
100 | }) | ||
101 | }) | 101 | }) |
102 | }) | 102 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { |
103 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 103 | let node = d.ast(db); |
104 | let node = d.ast(db); | 104 | let replacement = format!("Ok({})", node.syntax()); |
105 | let replacement = format!("Ok({})", node.syntax()); | 105 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); |
106 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); | 106 | let source_change = SourceFileEdit { file_id, edit }.into(); |
107 | let source_change = SourceFileEdit { file_id, edit }.into(); | 107 | let fix = Fix::new("Wrap with ok", source_change); |
108 | let fix = Fix::new("Wrap with ok", source_change); | 108 | res.borrow_mut().push(Diagnostic { |
109 | res.borrow_mut().push(Diagnostic { | 109 | range: sema.diagnostics_range(d).range, |
110 | range: sema.diagnostics_range(d).range, | 110 | message: d.message(), |
111 | message: d.message(), | 111 | severity: Severity::Error, |
112 | severity: Severity::Error, | 112 | fix: Some(fix), |
113 | fix: Some(fix), | 113 | }) |
114 | }) | 114 | }) |
115 | }) | 115 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
116 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 116 | res.borrow_mut().push(Diagnostic { |
117 | res.borrow_mut().push(Diagnostic { | 117 | range: sema.diagnostics_range(d).range, |
118 | range: sema.diagnostics_range(d).range, | 118 | message: d.message(), |
119 | message: d.message(), | 119 | severity: Severity::Error, |
120 | severity: Severity::Error, | 120 | fix: missing_struct_field_fix(&sema, file_id, d), |
121 | fix: missing_struct_field_fix(&sema, file_id, d), | 121 | }) |
122 | }) | 122 | }) |
123 | }); | 123 | // Only collect experimental diagnostics when they're enabled. |
124 | .filter(|diag| !diag.is_experimental() || enable_experimental) | ||
125 | // Diagnostics not handled above get no fix and default treatment. | ||
126 | .build(|d| { | ||
127 | res.borrow_mut().push(Diagnostic { | ||
128 | message: d.message(), | ||
129 | range: sema.diagnostics_range(d).range, | ||
130 | severity: Severity::Error, | ||
131 | fix: None, | ||
132 | }) | ||
133 | }); | ||
124 | 134 | ||
125 | if let Some(m) = sema.to_module_def(file_id) { | 135 | if let Some(m) = sema.to_module_def(file_id) { |
126 | m.diagnostics(db, &mut sink); | 136 | m.diagnostics(db, &mut sink); |
@@ -136,7 +146,7 @@ fn missing_struct_field_fix( | |||
136 | ) -> Option<Fix> { | 146 | ) -> Option<Fix> { |
137 | let record_expr = sema.ast(d); | 147 | let record_expr = sema.ast(d); |
138 | 148 | ||
139 | let record_lit = ast::RecordLit::cast(record_expr.syntax().parent()?.parent()?)?; | 149 | let record_lit = ast::RecordExpr::cast(record_expr.syntax().parent()?.parent()?)?; |
140 | let def_id = sema.resolve_variant(record_lit)?; | 150 | let def_id = sema.resolve_variant(record_lit)?; |
141 | let module; | 151 | let module; |
142 | let def_file_id; | 152 | let def_file_id; |
@@ -145,21 +155,21 @@ fn missing_struct_field_fix( | |||
145 | module = s.module(sema.db); | 155 | module = s.module(sema.db); |
146 | let source = s.source(sema.db); | 156 | let source = s.source(sema.db); |
147 | def_file_id = source.file_id; | 157 | def_file_id = source.file_id; |
148 | let fields = source.value.field_def_list()?; | 158 | let fields = source.value.field_list()?; |
149 | record_field_def_list(fields)? | 159 | record_field_list(fields)? |
150 | } | 160 | } |
151 | VariantDef::Union(u) => { | 161 | VariantDef::Union(u) => { |
152 | module = u.module(sema.db); | 162 | module = u.module(sema.db); |
153 | let source = u.source(sema.db); | 163 | let source = u.source(sema.db); |
154 | def_file_id = source.file_id; | 164 | def_file_id = source.file_id; |
155 | source.value.record_field_def_list()? | 165 | source.value.record_field_list()? |
156 | } | 166 | } |
157 | VariantDef::EnumVariant(e) => { | 167 | VariantDef::EnumVariant(e) => { |
158 | module = e.module(sema.db); | 168 | module = e.module(sema.db); |
159 | let source = e.source(sema.db); | 169 | let source = e.source(sema.db); |
160 | def_file_id = source.file_id; | 170 | def_file_id = source.file_id; |
161 | let fields = source.value.field_def_list()?; | 171 | let fields = source.value.field_list()?; |
162 | record_field_def_list(fields)? | 172 | record_field_list(fields)? |
163 | } | 173 | } |
164 | }; | 174 | }; |
165 | let def_file_id = def_file_id.original_file(sema.db); | 175 | let def_file_id = def_file_id.original_file(sema.db); |
@@ -195,10 +205,10 @@ fn missing_struct_field_fix( | |||
195 | let fix = Fix::new("Create field", source_change.into()); | 205 | let fix = Fix::new("Create field", source_change.into()); |
196 | return Some(fix); | 206 | return Some(fix); |
197 | 207 | ||
198 | fn record_field_def_list(field_def_list: ast::FieldDefList) -> Option<ast::RecordFieldDefList> { | 208 | fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> { |
199 | match field_def_list { | 209 | match field_def_list { |
200 | ast::FieldDefList::RecordFieldDefList(it) => Some(it), | 210 | ast::FieldList::RecordFieldList(it) => Some(it), |
201 | ast::FieldDefList::TupleFieldDefList(_) => None, | 211 | ast::FieldList::TupleFieldList(_) => None, |
202 | } | 212 | } |
203 | } | 213 | } |
204 | } | 214 | } |
@@ -253,8 +263,8 @@ fn check_struct_shorthand_initialization( | |||
253 | file_id: FileId, | 263 | file_id: FileId, |
254 | node: &SyntaxNode, | 264 | node: &SyntaxNode, |
255 | ) -> Option<()> { | 265 | ) -> Option<()> { |
256 | let record_lit = ast::RecordLit::cast(node.clone())?; | 266 | let record_lit = ast::RecordExpr::cast(node.clone())?; |
257 | let record_field_list = record_lit.record_field_list()?; | 267 | let record_field_list = record_lit.record_expr_field_list()?; |
258 | for record_field in record_field_list.fields() { | 268 | for record_field in record_field_list.fields() { |
259 | if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) { | 269 | if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) { |
260 | let field_name = name_ref.syntax().text().to_string(); | 270 | let field_name = name_ref.syntax().text().to_string(); |
@@ -298,7 +308,7 @@ mod tests { | |||
298 | let after = trim_indent(ra_fixture_after); | 308 | let after = trim_indent(ra_fixture_after); |
299 | 309 | ||
300 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); | 310 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); |
301 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); | 311 | let diagnostic = analysis.diagnostics(file_position.file_id, true).unwrap().pop().unwrap(); |
302 | let mut fix = diagnostic.fix.unwrap(); | 312 | let mut fix = diagnostic.fix.unwrap(); |
303 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | 313 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
304 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); | 314 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); |
@@ -324,7 +334,7 @@ mod tests { | |||
324 | let ra_fixture_after = &trim_indent(ra_fixture_after); | 334 | let ra_fixture_after = &trim_indent(ra_fixture_after); |
325 | let (analysis, file_pos) = analysis_and_position(ra_fixture_before); | 335 | let (analysis, file_pos) = analysis_and_position(ra_fixture_before); |
326 | let current_file_id = file_pos.file_id; | 336 | let current_file_id = file_pos.file_id; |
327 | let diagnostic = analysis.diagnostics(current_file_id).unwrap().pop().unwrap(); | 337 | let diagnostic = analysis.diagnostics(current_file_id, true).unwrap().pop().unwrap(); |
328 | let mut fix = diagnostic.fix.unwrap(); | 338 | let mut fix = diagnostic.fix.unwrap(); |
329 | let edit = fix.source_change.source_file_edits.pop().unwrap(); | 339 | let edit = fix.source_change.source_file_edits.pop().unwrap(); |
330 | let changed_file_id = edit.file_id; | 340 | let changed_file_id = edit.file_id; |
@@ -345,14 +355,14 @@ mod tests { | |||
345 | let analysis = mock.analysis(); | 355 | let analysis = mock.analysis(); |
346 | let diagnostics = files | 356 | let diagnostics = files |
347 | .into_iter() | 357 | .into_iter() |
348 | .flat_map(|file_id| analysis.diagnostics(file_id).unwrap()) | 358 | .flat_map(|file_id| analysis.diagnostics(file_id, true).unwrap()) |
349 | .collect::<Vec<_>>(); | 359 | .collect::<Vec<_>>(); |
350 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); | 360 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); |
351 | } | 361 | } |
352 | 362 | ||
353 | fn check_expect(ra_fixture: &str, expect: Expect) { | 363 | fn check_expect(ra_fixture: &str, expect: Expect) { |
354 | let (analysis, file_id) = single_file(ra_fixture); | 364 | let (analysis, file_id) = single_file(ra_fixture); |
355 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | 365 | let diagnostics = analysis.diagnostics(file_id, true).unwrap(); |
356 | expect.assert_debug_eq(&diagnostics) | 366 | expect.assert_debug_eq(&diagnostics) |
357 | } | 367 | } |
358 | 368 | ||
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index 6d4151dd8..fd42aa435 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs | |||
@@ -5,7 +5,7 @@ mod navigation_target; | |||
5 | mod short_label; | 5 | mod short_label; |
6 | 6 | ||
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, | 8 | ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner}, |
9 | SyntaxKind::{ATTR, COMMENT}, | 9 | SyntaxKind::{ATTR, COMMENT}, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -16,7 +16,7 @@ pub use navigation_target::NavigationTarget; | |||
16 | pub(crate) use navigation_target::{ToNav, TryToNav}; | 16 | pub(crate) use navigation_target::{ToNav, TryToNav}; |
17 | pub(crate) use short_label::ShortLabel; | 17 | pub(crate) use short_label::ShortLabel; |
18 | 18 | ||
19 | pub(crate) fn function_declaration(node: &ast::FnDef) -> String { | 19 | pub(crate) fn function_declaration(node: &ast::Fn) -> String { |
20 | let mut buf = String::new(); | 20 | let mut buf = String::new(); |
21 | if let Some(vis) = node.visibility() { | 21 | if let Some(vis) = node.visibility() { |
22 | format_to!(buf, "{} ", vis); | 22 | format_to!(buf, "{} ", vis); |
@@ -37,14 +37,14 @@ pub(crate) fn function_declaration(node: &ast::FnDef) -> String { | |||
37 | if let Some(name) = node.name() { | 37 | if let Some(name) = node.name() { |
38 | format_to!(buf, "fn {}", name) | 38 | format_to!(buf, "fn {}", name) |
39 | } | 39 | } |
40 | if let Some(type_params) = node.type_param_list() { | 40 | if let Some(type_params) = node.generic_param_list() { |
41 | format_to!(buf, "{}", type_params); | 41 | format_to!(buf, "{}", type_params); |
42 | } | 42 | } |
43 | if let Some(param_list) = node.param_list() { | 43 | if let Some(param_list) = node.param_list() { |
44 | format_to!(buf, "{}", param_list); | 44 | format_to!(buf, "{}", param_list); |
45 | } | 45 | } |
46 | if let Some(ret_type) = node.ret_type() { | 46 | if let Some(ret_type) = node.ret_type() { |
47 | if ret_type.type_ref().is_some() { | 47 | if ret_type.ty().is_some() { |
48 | format_to!(buf, " {}", ret_type); | 48 | format_to!(buf, " {}", ret_type); |
49 | } | 49 | } |
50 | } | 50 | } |
@@ -54,7 +54,7 @@ pub(crate) fn function_declaration(node: &ast::FnDef) -> String { | |||
54 | buf | 54 | buf |
55 | } | 55 | } |
56 | 56 | ||
57 | pub(crate) fn const_label(node: &ast::ConstDef) -> String { | 57 | pub(crate) fn const_label(node: &ast::Const) -> String { |
58 | let label: String = node | 58 | let label: String = node |
59 | .syntax() | 59 | .syntax() |
60 | .children_with_tokens() | 60 | .children_with_tokens() |
@@ -65,7 +65,7 @@ pub(crate) fn const_label(node: &ast::ConstDef) -> String { | |||
65 | label.trim().to_owned() | 65 | label.trim().to_owned() |
66 | } | 66 | } |
67 | 67 | ||
68 | pub(crate) fn type_label(node: &ast::TypeAliasDef) -> String { | 68 | pub(crate) fn type_label(node: &ast::TypeAlias) -> String { |
69 | let label: String = node | 69 | let label: String = node |
70 | .syntax() | 70 | .syntax() |
71 | .children_with_tokens() | 71 | .children_with_tokens() |
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index fd245705c..45fbc86ef 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs | |||
@@ -379,16 +379,16 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option | |||
379 | 379 | ||
380 | match_ast! { | 380 | match_ast! { |
381 | match node { | 381 | match node { |
382 | ast::FnDef(it) => it.doc_comment_text(), | 382 | ast::Fn(it) => it.doc_comment_text(), |
383 | ast::StructDef(it) => it.doc_comment_text(), | 383 | ast::Struct(it) => it.doc_comment_text(), |
384 | ast::EnumDef(it) => it.doc_comment_text(), | 384 | ast::Enum(it) => it.doc_comment_text(), |
385 | ast::TraitDef(it) => it.doc_comment_text(), | 385 | ast::Trait(it) => it.doc_comment_text(), |
386 | ast::Module(it) => it.doc_comment_text(), | 386 | ast::Module(it) => it.doc_comment_text(), |
387 | ast::TypeAliasDef(it) => it.doc_comment_text(), | 387 | ast::TypeAlias(it) => it.doc_comment_text(), |
388 | ast::ConstDef(it) => it.doc_comment_text(), | 388 | ast::Const(it) => it.doc_comment_text(), |
389 | ast::StaticDef(it) => it.doc_comment_text(), | 389 | ast::Static(it) => it.doc_comment_text(), |
390 | ast::RecordFieldDef(it) => it.doc_comment_text(), | 390 | ast::RecordField(it) => it.doc_comment_text(), |
391 | ast::EnumVariant(it) => it.doc_comment_text(), | 391 | ast::Variant(it) => it.doc_comment_text(), |
392 | ast::MacroCall(it) => it.doc_comment_text(), | 392 | ast::MacroCall(it) => it.doc_comment_text(), |
393 | _ => None, | 393 | _ => None, |
394 | } | 394 | } |
@@ -404,16 +404,16 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> | |||
404 | 404 | ||
405 | match_ast! { | 405 | match_ast! { |
406 | match node { | 406 | match node { |
407 | ast::FnDef(it) => it.short_label(), | 407 | ast::Fn(it) => it.short_label(), |
408 | ast::StructDef(it) => it.short_label(), | 408 | ast::Struct(it) => it.short_label(), |
409 | ast::EnumDef(it) => it.short_label(), | 409 | ast::Enum(it) => it.short_label(), |
410 | ast::TraitDef(it) => it.short_label(), | 410 | ast::Trait(it) => it.short_label(), |
411 | ast::Module(it) => it.short_label(), | 411 | ast::Module(it) => it.short_label(), |
412 | ast::TypeAliasDef(it) => it.short_label(), | 412 | ast::TypeAlias(it) => it.short_label(), |
413 | ast::ConstDef(it) => it.short_label(), | 413 | ast::Const(it) => it.short_label(), |
414 | ast::StaticDef(it) => it.short_label(), | 414 | ast::Static(it) => it.short_label(), |
415 | ast::RecordFieldDef(it) => it.short_label(), | 415 | ast::RecordField(it) => it.short_label(), |
416 | ast::EnumVariant(it) => it.short_label(), | 416 | ast::Variant(it) => it.short_label(), |
417 | _ => None, | 417 | _ => None, |
418 | } | 418 | } |
419 | } | 419 | } |
@@ -446,7 +446,7 @@ fn foo() { enum FooInner { } } | |||
446 | 5..13, | 446 | 5..13, |
447 | ), | 447 | ), |
448 | name: "FooInner", | 448 | name: "FooInner", |
449 | kind: ENUM_DEF, | 449 | kind: ENUM, |
450 | container_name: None, | 450 | container_name: None, |
451 | description: Some( | 451 | description: Some( |
452 | "enum FooInner", | 452 | "enum FooInner", |
@@ -462,7 +462,7 @@ fn foo() { enum FooInner { } } | |||
462 | 34..42, | 462 | 34..42, |
463 | ), | 463 | ), |
464 | name: "FooInner", | 464 | name: "FooInner", |
465 | kind: ENUM_DEF, | 465 | kind: ENUM, |
466 | container_name: Some( | 466 | container_name: Some( |
467 | "foo", | 467 | "foo", |
468 | ), | 468 | ), |
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index 5588130a1..0fdf8e9a5 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs | |||
@@ -1,37 +1,37 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner}; | 3 | use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; |
4 | use stdx::format_to; | 4 | use stdx::format_to; |
5 | 5 | ||
6 | pub(crate) trait ShortLabel { | 6 | pub(crate) trait ShortLabel { |
7 | fn short_label(&self) -> Option<String>; | 7 | fn short_label(&self) -> Option<String>; |
8 | } | 8 | } |
9 | 9 | ||
10 | impl ShortLabel for ast::FnDef { | 10 | impl ShortLabel for ast::Fn { |
11 | fn short_label(&self) -> Option<String> { | 11 | fn short_label(&self) -> Option<String> { |
12 | Some(crate::display::function_declaration(self)) | 12 | Some(crate::display::function_declaration(self)) |
13 | } | 13 | } |
14 | } | 14 | } |
15 | 15 | ||
16 | impl ShortLabel for ast::StructDef { | 16 | impl ShortLabel for ast::Struct { |
17 | fn short_label(&self) -> Option<String> { | 17 | fn short_label(&self) -> Option<String> { |
18 | short_label_from_node(self, "struct ") | 18 | short_label_from_node(self, "struct ") |
19 | } | 19 | } |
20 | } | 20 | } |
21 | 21 | ||
22 | impl ShortLabel for ast::UnionDef { | 22 | impl ShortLabel for ast::Union { |
23 | fn short_label(&self) -> Option<String> { | 23 | fn short_label(&self) -> Option<String> { |
24 | short_label_from_node(self, "union ") | 24 | short_label_from_node(self, "union ") |
25 | } | 25 | } |
26 | } | 26 | } |
27 | 27 | ||
28 | impl ShortLabel for ast::EnumDef { | 28 | impl ShortLabel for ast::Enum { |
29 | fn short_label(&self) -> Option<String> { | 29 | fn short_label(&self) -> Option<String> { |
30 | short_label_from_node(self, "enum ") | 30 | short_label_from_node(self, "enum ") |
31 | } | 31 | } |
32 | } | 32 | } |
33 | 33 | ||
34 | impl ShortLabel for ast::TraitDef { | 34 | impl ShortLabel for ast::Trait { |
35 | fn short_label(&self) -> Option<String> { | 35 | fn short_label(&self) -> Option<String> { |
36 | if self.unsafe_token().is_some() { | 36 | if self.unsafe_token().is_some() { |
37 | short_label_from_node(self, "unsafe trait ") | 37 | short_label_from_node(self, "unsafe trait ") |
@@ -47,43 +47,43 @@ impl ShortLabel for ast::Module { | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | impl ShortLabel for ast::TypeAliasDef { | 50 | impl ShortLabel for ast::TypeAlias { |
51 | fn short_label(&self) -> Option<String> { | 51 | fn short_label(&self) -> Option<String> { |
52 | short_label_from_node(self, "type ") | 52 | short_label_from_node(self, "type ") |
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
56 | impl ShortLabel for ast::ConstDef { | 56 | impl ShortLabel for ast::Const { |
57 | fn short_label(&self) -> Option<String> { | 57 | fn short_label(&self) -> Option<String> { |
58 | short_label_from_ascribed_node(self, "const ") | 58 | short_label_from_ty(self, self.ty(), "const ") |
59 | } | 59 | } |
60 | } | 60 | } |
61 | 61 | ||
62 | impl ShortLabel for ast::StaticDef { | 62 | impl ShortLabel for ast::Static { |
63 | fn short_label(&self) -> Option<String> { | 63 | fn short_label(&self) -> Option<String> { |
64 | short_label_from_ascribed_node(self, "static ") | 64 | short_label_from_ty(self, self.ty(), "static ") |
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | impl ShortLabel for ast::RecordFieldDef { | 68 | impl ShortLabel for ast::RecordField { |
69 | fn short_label(&self) -> Option<String> { | 69 | fn short_label(&self) -> Option<String> { |
70 | short_label_from_ascribed_node(self, "") | 70 | short_label_from_ty(self, self.ty(), "") |
71 | } | 71 | } |
72 | } | 72 | } |
73 | 73 | ||
74 | impl ShortLabel for ast::EnumVariant { | 74 | impl ShortLabel for ast::Variant { |
75 | fn short_label(&self) -> Option<String> { | 75 | fn short_label(&self) -> Option<String> { |
76 | Some(self.name()?.text().to_string()) | 76 | Some(self.name()?.text().to_string()) |
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | fn short_label_from_ascribed_node<T>(node: &T, prefix: &str) -> Option<String> | 80 | fn short_label_from_ty<T>(node: &T, ty: Option<ast::Type>, prefix: &str) -> Option<String> |
81 | where | 81 | where |
82 | T: NameOwner + VisibilityOwner + TypeAscriptionOwner, | 82 | T: NameOwner + VisibilityOwner, |
83 | { | 83 | { |
84 | let mut buf = short_label_from_node(node, prefix)?; | 84 | let mut buf = short_label_from_node(node, prefix)?; |
85 | 85 | ||
86 | if let Some(type_ref) = node.ascribed_type() { | 86 | if let Some(type_ref) = ty { |
87 | format_to!(buf, ": {}", type_ref.syntax()); | 87 | format_to!(buf, ": {}", type_ref.syntax()); |
88 | } | 88 | } |
89 | 89 | ||
diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index 8a6b3ea99..fc81b48cc 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs | |||
@@ -39,12 +39,12 @@ fn try_extend_selection( | |||
39 | let list_kinds = [ | 39 | let list_kinds = [ |
40 | RECORD_FIELD_PAT_LIST, | 40 | RECORD_FIELD_PAT_LIST, |
41 | MATCH_ARM_LIST, | 41 | MATCH_ARM_LIST, |
42 | RECORD_FIELD_DEF_LIST, | ||
43 | TUPLE_FIELD_DEF_LIST, | ||
44 | RECORD_FIELD_LIST, | 42 | RECORD_FIELD_LIST, |
45 | ENUM_VARIANT_LIST, | 43 | TUPLE_FIELD_LIST, |
44 | RECORD_EXPR_FIELD_LIST, | ||
45 | VARIANT_LIST, | ||
46 | USE_TREE_LIST, | 46 | USE_TREE_LIST, |
47 | TYPE_PARAM_LIST, | 47 | GENERIC_PARAM_LIST, |
48 | TYPE_ARG_LIST, | 48 | TYPE_ARG_LIST, |
49 | TYPE_BOUND_LIST, | 49 | TYPE_BOUND_LIST, |
50 | PARAM_LIST, | 50 | PARAM_LIST, |
diff --git a/crates/ra_ide/src/file_structure.rs b/crates/ra_ide/src/file_structure.rs index 1f6a3febf..ef368651a 100644 --- a/crates/ra_ide/src/file_structure.rs +++ b/crates/ra_ide/src/file_structure.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner}, | 2 | ast::{self, AttrsOwner, GenericParamsOwner, NameOwner}, |
3 | match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent, | 3 | match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent, |
4 | }; | 4 | }; |
5 | 5 | ||
@@ -52,19 +52,12 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { | |||
52 | 52 | ||
53 | fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | 53 | fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { |
54 | fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> { | 54 | fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> { |
55 | decl_with_detail(node, None) | 55 | decl_with_detail(&node, None) |
56 | } | ||
57 | |||
58 | fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>( | ||
59 | node: N, | ||
60 | ) -> Option<StructureNode> { | ||
61 | let ty = node.ascribed_type(); | ||
62 | decl_with_type_ref(node, ty) | ||
63 | } | 56 | } |
64 | 57 | ||
65 | fn decl_with_type_ref<N: NameOwner + AttrsOwner>( | 58 | fn decl_with_type_ref<N: NameOwner + AttrsOwner>( |
66 | node: N, | 59 | node: &N, |
67 | type_ref: Option<ast::TypeRef>, | 60 | type_ref: Option<ast::Type>, |
68 | ) -> Option<StructureNode> { | 61 | ) -> Option<StructureNode> { |
69 | let detail = type_ref.map(|type_ref| { | 62 | let detail = type_ref.map(|type_ref| { |
70 | let mut detail = String::new(); | 63 | let mut detail = String::new(); |
@@ -75,7 +68,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | |||
75 | } | 68 | } |
76 | 69 | ||
77 | fn decl_with_detail<N: NameOwner + AttrsOwner>( | 70 | fn decl_with_detail<N: NameOwner + AttrsOwner>( |
78 | node: N, | 71 | node: &N, |
79 | detail: Option<String>, | 72 | detail: Option<String>, |
80 | ) -> Option<StructureNode> { | 73 | ) -> Option<StructureNode> { |
81 | let name = node.name()?; | 74 | let name = node.name()?; |
@@ -111,9 +104,9 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | |||
111 | 104 | ||
112 | match_ast! { | 105 | match_ast! { |
113 | match node { | 106 | match node { |
114 | ast::FnDef(it) => { | 107 | ast::Fn(it) => { |
115 | let mut detail = String::from("fn"); | 108 | let mut detail = String::from("fn"); |
116 | if let Some(type_param_list) = it.type_param_list() { | 109 | if let Some(type_param_list) = it.generic_param_list() { |
117 | collapse_ws(type_param_list.syntax(), &mut detail); | 110 | collapse_ws(type_param_list.syntax(), &mut detail); |
118 | } | 111 | } |
119 | if let Some(param_list) = it.param_list() { | 112 | if let Some(param_list) = it.param_list() { |
@@ -124,22 +117,19 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | |||
124 | collapse_ws(ret_type.syntax(), &mut detail); | 117 | collapse_ws(ret_type.syntax(), &mut detail); |
125 | } | 118 | } |
126 | 119 | ||
127 | decl_with_detail(it, Some(detail)) | 120 | decl_with_detail(&it, Some(detail)) |
128 | }, | 121 | }, |
129 | ast::StructDef(it) => decl(it), | 122 | ast::Struct(it) => decl(it), |
130 | ast::UnionDef(it) => decl(it), | 123 | ast::Union(it) => decl(it), |
131 | ast::EnumDef(it) => decl(it), | 124 | ast::Enum(it) => decl(it), |
132 | ast::EnumVariant(it) => decl(it), | 125 | ast::Variant(it) => decl(it), |
133 | ast::TraitDef(it) => decl(it), | 126 | ast::Trait(it) => decl(it), |
134 | ast::Module(it) => decl(it), | 127 | ast::Module(it) => decl(it), |
135 | ast::TypeAliasDef(it) => { | 128 | ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty()), |
136 | let ty = it.type_ref(); | 129 | ast::RecordField(it) => decl_with_type_ref(&it, it.ty()), |
137 | decl_with_type_ref(it, ty) | 130 | ast::Const(it) => decl_with_type_ref(&it, it.ty()), |
138 | }, | 131 | ast::Static(it) => decl_with_type_ref(&it, it.ty()), |
139 | ast::RecordFieldDef(it) => decl_with_ascription(it), | 132 | ast::Impl(it) => { |
140 | ast::ConstDef(it) => decl_with_ascription(it), | ||
141 | ast::StaticDef(it) => decl_with_ascription(it), | ||
142 | ast::ImplDef(it) => { | ||
143 | let target_type = it.target_type()?; | 133 | let target_type = it.target_type()?; |
144 | let target_trait = it.target_trait(); | 134 | let target_trait = it.target_trait(); |
145 | let label = match target_trait { | 135 | let label = match target_trait { |
@@ -238,7 +228,7 @@ fn very_obsolete() {} | |||
238 | label: "Foo", | 228 | label: "Foo", |
239 | navigation_range: 8..11, | 229 | navigation_range: 8..11, |
240 | node_range: 1..26, | 230 | node_range: 1..26, |
241 | kind: STRUCT_DEF, | 231 | kind: STRUCT, |
242 | detail: None, | 232 | detail: None, |
243 | deprecated: false, | 233 | deprecated: false, |
244 | }, | 234 | }, |
@@ -249,7 +239,7 @@ fn very_obsolete() {} | |||
249 | label: "x", | 239 | label: "x", |
250 | navigation_range: 18..19, | 240 | navigation_range: 18..19, |
251 | node_range: 18..24, | 241 | node_range: 18..24, |
252 | kind: RECORD_FIELD_DEF, | 242 | kind: RECORD_FIELD, |
253 | detail: Some( | 243 | detail: Some( |
254 | "i32", | 244 | "i32", |
255 | ), | 245 | ), |
@@ -271,7 +261,7 @@ fn very_obsolete() {} | |||
271 | label: "bar1", | 261 | label: "bar1", |
272 | navigation_range: 43..47, | 262 | navigation_range: 43..47, |
273 | node_range: 40..52, | 263 | node_range: 40..52, |
274 | kind: FN_DEF, | 264 | kind: FN, |
275 | detail: Some( | 265 | detail: Some( |
276 | "fn()", | 266 | "fn()", |
277 | ), | 267 | ), |
@@ -284,7 +274,7 @@ fn very_obsolete() {} | |||
284 | label: "bar2", | 274 | label: "bar2", |
285 | navigation_range: 60..64, | 275 | navigation_range: 60..64, |
286 | node_range: 57..81, | 276 | node_range: 57..81, |
287 | kind: FN_DEF, | 277 | kind: FN, |
288 | detail: Some( | 278 | detail: Some( |
289 | "fn<T>(t: T) -> T", | 279 | "fn<T>(t: T) -> T", |
290 | ), | 280 | ), |
@@ -297,7 +287,7 @@ fn very_obsolete() {} | |||
297 | label: "bar3", | 287 | label: "bar3", |
298 | navigation_range: 89..93, | 288 | navigation_range: 89..93, |
299 | node_range: 86..156, | 289 | node_range: 86..156, |
300 | kind: FN_DEF, | 290 | kind: FN, |
301 | detail: Some( | 291 | detail: Some( |
302 | "fn<A, B>(a: A, b: B) -> Vec< u32 >", | 292 | "fn<A, B>(a: A, b: B) -> Vec< u32 >", |
303 | ), | 293 | ), |
@@ -308,7 +298,7 @@ fn very_obsolete() {} | |||
308 | label: "E", | 298 | label: "E", |
309 | navigation_range: 165..166, | 299 | navigation_range: 165..166, |
310 | node_range: 160..180, | 300 | node_range: 160..180, |
311 | kind: ENUM_DEF, | 301 | kind: ENUM, |
312 | detail: None, | 302 | detail: None, |
313 | deprecated: false, | 303 | deprecated: false, |
314 | }, | 304 | }, |
@@ -319,7 +309,7 @@ fn very_obsolete() {} | |||
319 | label: "X", | 309 | label: "X", |
320 | navigation_range: 169..170, | 310 | navigation_range: 169..170, |
321 | node_range: 169..170, | 311 | node_range: 169..170, |
322 | kind: ENUM_VARIANT, | 312 | kind: VARIANT, |
323 | detail: None, | 313 | detail: None, |
324 | deprecated: false, | 314 | deprecated: false, |
325 | }, | 315 | }, |
@@ -330,7 +320,7 @@ fn very_obsolete() {} | |||
330 | label: "Y", | 320 | label: "Y", |
331 | navigation_range: 172..173, | 321 | navigation_range: 172..173, |
332 | node_range: 172..178, | 322 | node_range: 172..178, |
333 | kind: ENUM_VARIANT, | 323 | kind: VARIANT, |
334 | detail: None, | 324 | detail: None, |
335 | deprecated: false, | 325 | deprecated: false, |
336 | }, | 326 | }, |
@@ -339,7 +329,7 @@ fn very_obsolete() {} | |||
339 | label: "T", | 329 | label: "T", |
340 | navigation_range: 186..187, | 330 | navigation_range: 186..187, |
341 | node_range: 181..193, | 331 | node_range: 181..193, |
342 | kind: TYPE_ALIAS_DEF, | 332 | kind: TYPE_ALIAS, |
343 | detail: Some( | 333 | detail: Some( |
344 | "()", | 334 | "()", |
345 | ), | 335 | ), |
@@ -350,7 +340,7 @@ fn very_obsolete() {} | |||
350 | label: "S", | 340 | label: "S", |
351 | navigation_range: 201..202, | 341 | navigation_range: 201..202, |
352 | node_range: 194..213, | 342 | node_range: 194..213, |
353 | kind: STATIC_DEF, | 343 | kind: STATIC, |
354 | detail: Some( | 344 | detail: Some( |
355 | "i32", | 345 | "i32", |
356 | ), | 346 | ), |
@@ -361,7 +351,7 @@ fn very_obsolete() {} | |||
361 | label: "C", | 351 | label: "C", |
362 | navigation_range: 220..221, | 352 | navigation_range: 220..221, |
363 | node_range: 214..232, | 353 | node_range: 214..232, |
364 | kind: CONST_DEF, | 354 | kind: CONST, |
365 | detail: Some( | 355 | detail: Some( |
366 | "i32", | 356 | "i32", |
367 | ), | 357 | ), |
@@ -372,7 +362,7 @@ fn very_obsolete() {} | |||
372 | label: "impl E", | 362 | label: "impl E", |
373 | navigation_range: 239..240, | 363 | navigation_range: 239..240, |
374 | node_range: 234..243, | 364 | node_range: 234..243, |
375 | kind: IMPL_DEF, | 365 | kind: IMPL, |
376 | detail: None, | 366 | detail: None, |
377 | deprecated: false, | 367 | deprecated: false, |
378 | }, | 368 | }, |
@@ -381,7 +371,7 @@ fn very_obsolete() {} | |||
381 | label: "impl fmt::Debug for E", | 371 | label: "impl fmt::Debug for E", |
382 | navigation_range: 265..266, | 372 | navigation_range: 265..266, |
383 | node_range: 245..269, | 373 | node_range: 245..269, |
384 | kind: IMPL_DEF, | 374 | kind: IMPL, |
385 | detail: None, | 375 | detail: None, |
386 | deprecated: false, | 376 | deprecated: false, |
387 | }, | 377 | }, |
@@ -417,7 +407,7 @@ fn very_obsolete() {} | |||
417 | label: "obsolete", | 407 | label: "obsolete", |
418 | navigation_range: 428..436, | 408 | navigation_range: 428..436, |
419 | node_range: 411..441, | 409 | node_range: 411..441, |
420 | kind: FN_DEF, | 410 | kind: FN, |
421 | detail: Some( | 411 | detail: Some( |
422 | "fn()", | 412 | "fn()", |
423 | ), | 413 | ), |
@@ -428,7 +418,7 @@ fn very_obsolete() {} | |||
428 | label: "very_obsolete", | 418 | label: "very_obsolete", |
429 | navigation_range: 481..494, | 419 | navigation_range: 481..494, |
430 | node_range: 443..499, | 420 | node_range: 443..499, |
431 | kind: FN_DEF, | 421 | kind: FN, |
432 | detail: Some( | 422 | detail: Some( |
433 | "fn()", | 423 | "fn()", |
434 | ), | 424 | ), |
diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs index e7ec9953f..5a6e17936 100644 --- a/crates/ra_ide/src/folding_ranges.rs +++ b/crates/ra_ide/src/folding_ranges.rs | |||
@@ -58,7 +58,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> { | |||
58 | } | 58 | } |
59 | NodeOrToken::Node(node) => { | 59 | NodeOrToken::Node(node) => { |
60 | // Fold groups of imports | 60 | // Fold groups of imports |
61 | if node.kind() == USE_ITEM && !visited_imports.contains(&node) { | 61 | if node.kind() == USE && !visited_imports.contains(&node) { |
62 | if let Some(range) = contiguous_range_for_group(&node, &mut visited_imports) { | 62 | if let Some(range) = contiguous_range_for_group(&node, &mut visited_imports) { |
63 | res.push(Fold { range, kind: FoldKind::Imports }) | 63 | res.push(Fold { range, kind: FoldKind::Imports }) |
64 | } | 64 | } |
@@ -83,17 +83,17 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> { | |||
83 | fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { | 83 | fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { |
84 | match kind { | 84 | match kind { |
85 | COMMENT => Some(FoldKind::Comment), | 85 | COMMENT => Some(FoldKind::Comment), |
86 | USE_ITEM => Some(FoldKind::Imports), | 86 | USE => Some(FoldKind::Imports), |
87 | ARG_LIST => Some(FoldKind::ArgList), | 87 | ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), |
88 | RECORD_FIELD_DEF_LIST | 88 | RECORD_FIELD_LIST |
89 | | RECORD_FIELD_PAT_LIST | 89 | | RECORD_FIELD_PAT_LIST |
90 | | RECORD_FIELD_LIST | 90 | | RECORD_EXPR_FIELD_LIST |
91 | | ITEM_LIST | 91 | | ITEM_LIST |
92 | | EXTERN_ITEM_LIST | 92 | | EXTERN_ITEM_LIST |
93 | | USE_TREE_LIST | 93 | | USE_TREE_LIST |
94 | | BLOCK_EXPR | 94 | | BLOCK_EXPR |
95 | | MATCH_ARM_LIST | 95 | | MATCH_ARM_LIST |
96 | | ENUM_VARIANT_LIST | 96 | | VARIANT_LIST |
97 | | TOKEN_TREE => Some(FoldKind::Block), | 97 | | TOKEN_TREE => Some(FoldKind::Block), |
98 | _ => None, | 98 | _ => None, |
99 | } | 99 | } |
@@ -386,4 +386,16 @@ const _: S = S <fold block>{ | |||
386 | "#, | 386 | "#, |
387 | ) | 387 | ) |
388 | } | 388 | } |
389 | |||
390 | #[test] | ||
391 | fn fold_multiline_params() { | ||
392 | check( | ||
393 | r#" | ||
394 | fn foo<fold arglist>( | ||
395 | x: i32, | ||
396 | y: String, | ||
397 | )</fold> {} | ||
398 | "#, | ||
399 | ) | ||
400 | } | ||
389 | } | 401 | } |
diff --git a/crates/ra_ide/src/goto_implementation.rs b/crates/ra_ide/src/goto_implementation.rs index 3ee048f28..9912b7142 100644 --- a/crates/ra_ide/src/goto_implementation.rs +++ b/crates/ra_ide/src/goto_implementation.rs | |||
@@ -23,12 +23,12 @@ pub(crate) fn goto_implementation( | |||
23 | 23 | ||
24 | let krate = sema.to_module_def(position.file_id)?.krate(); | 24 | let krate = sema.to_module_def(position.file_id)?.krate(); |
25 | 25 | ||
26 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { | 26 | if let Some(nominal_def) = find_node_at_offset::<ast::AdtDef>(&syntax, position.offset) { |
27 | return Some(RangeInfo::new( | 27 | return Some(RangeInfo::new( |
28 | nominal_def.syntax().text_range(), | 28 | nominal_def.syntax().text_range(), |
29 | impls_for_def(&sema, &nominal_def, krate)?, | 29 | impls_for_def(&sema, &nominal_def, krate)?, |
30 | )); | 30 | )); |
31 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { | 31 | } else if let Some(trait_def) = find_node_at_offset::<ast::Trait>(&syntax, position.offset) { |
32 | return Some(RangeInfo::new( | 32 | return Some(RangeInfo::new( |
33 | trait_def.syntax().text_range(), | 33 | trait_def.syntax().text_range(), |
34 | impls_for_trait(&sema, &trait_def, krate)?, | 34 | impls_for_trait(&sema, &trait_def, krate)?, |
@@ -40,13 +40,13 @@ pub(crate) fn goto_implementation( | |||
40 | 40 | ||
41 | fn impls_for_def( | 41 | fn impls_for_def( |
42 | sema: &Semantics<RootDatabase>, | 42 | sema: &Semantics<RootDatabase>, |
43 | node: &ast::NominalDef, | 43 | node: &ast::AdtDef, |
44 | krate: Crate, | 44 | krate: Crate, |
45 | ) -> Option<Vec<NavigationTarget>> { | 45 | ) -> Option<Vec<NavigationTarget>> { |
46 | let ty = match node { | 46 | let ty = match node { |
47 | ast::NominalDef::StructDef(def) => sema.to_def(def)?.ty(sema.db), | 47 | ast::AdtDef::Struct(def) => sema.to_def(def)?.ty(sema.db), |
48 | ast::NominalDef::EnumDef(def) => sema.to_def(def)?.ty(sema.db), | 48 | ast::AdtDef::Enum(def) => sema.to_def(def)?.ty(sema.db), |
49 | ast::NominalDef::UnionDef(def) => sema.to_def(def)?.ty(sema.db), | 49 | ast::AdtDef::Union(def) => sema.to_def(def)?.ty(sema.db), |
50 | }; | 50 | }; |
51 | 51 | ||
52 | let impls = ImplDef::all_in_crate(sema.db, krate); | 52 | let impls = ImplDef::all_in_crate(sema.db, krate); |
@@ -62,7 +62,7 @@ fn impls_for_def( | |||
62 | 62 | ||
63 | fn impls_for_trait( | 63 | fn impls_for_trait( |
64 | sema: &Semantics<RootDatabase>, | 64 | sema: &Semantics<RootDatabase>, |
65 | node: &ast::TraitDef, | 65 | node: &ast::Trait, |
66 | krate: Crate, | 66 | krate: Crate, |
67 | ) -> Option<Vec<NavigationTarget>> { | 67 | ) -> Option<Vec<NavigationTarget>> { |
68 | let tr = sema.to_def(node)?; | 68 | let tr = sema.to_def(node)?; |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index d067c339d..aa48cb412 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -1361,7 +1361,7 @@ fn foo_<|>test() {} | |||
1361 | 11..19, | 1361 | 11..19, |
1362 | ), | 1362 | ), |
1363 | name: "foo_test", | 1363 | name: "foo_test", |
1364 | kind: FN_DEF, | 1364 | kind: FN, |
1365 | container_name: None, | 1365 | container_name: None, |
1366 | description: None, | 1366 | description: None, |
1367 | docs: None, | 1367 | docs: None, |
@@ -1443,7 +1443,7 @@ fn main() { let s<|>t = S{ f1:0 }; } | |||
1443 | 7..8, | 1443 | 7..8, |
1444 | ), | 1444 | ), |
1445 | name: "S", | 1445 | name: "S", |
1446 | kind: STRUCT_DEF, | 1446 | kind: STRUCT, |
1447 | container_name: None, | 1447 | container_name: None, |
1448 | description: Some( | 1448 | description: Some( |
1449 | "struct S", | 1449 | "struct S", |
@@ -1482,7 +1482,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; } | |||
1482 | 24..25, | 1482 | 24..25, |
1483 | ), | 1483 | ), |
1484 | name: "S", | 1484 | name: "S", |
1485 | kind: STRUCT_DEF, | 1485 | kind: STRUCT, |
1486 | container_name: None, | 1486 | container_name: None, |
1487 | description: Some( | 1487 | description: Some( |
1488 | "struct S", | 1488 | "struct S", |
@@ -1501,7 +1501,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; } | |||
1501 | 7..10, | 1501 | 7..10, |
1502 | ), | 1502 | ), |
1503 | name: "Arg", | 1503 | name: "Arg", |
1504 | kind: STRUCT_DEF, | 1504 | kind: STRUCT, |
1505 | container_name: None, | 1505 | container_name: None, |
1506 | description: Some( | 1506 | description: Some( |
1507 | "struct Arg", | 1507 | "struct Arg", |
@@ -1540,7 +1540,7 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; } | |||
1540 | 24..25, | 1540 | 24..25, |
1541 | ), | 1541 | ), |
1542 | name: "S", | 1542 | name: "S", |
1543 | kind: STRUCT_DEF, | 1543 | kind: STRUCT, |
1544 | container_name: None, | 1544 | container_name: None, |
1545 | description: Some( | 1545 | description: Some( |
1546 | "struct S", | 1546 | "struct S", |
@@ -1559,7 +1559,7 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; } | |||
1559 | 7..10, | 1559 | 7..10, |
1560 | ), | 1560 | ), |
1561 | name: "Arg", | 1561 | name: "Arg", |
1562 | kind: STRUCT_DEF, | 1562 | kind: STRUCT, |
1563 | container_name: None, | 1563 | container_name: None, |
1564 | description: Some( | 1564 | description: Some( |
1565 | "struct Arg", | 1565 | "struct Arg", |
@@ -1601,7 +1601,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); } | |||
1601 | 7..8, | 1601 | 7..8, |
1602 | ), | 1602 | ), |
1603 | name: "A", | 1603 | name: "A", |
1604 | kind: STRUCT_DEF, | 1604 | kind: STRUCT, |
1605 | container_name: None, | 1605 | container_name: None, |
1606 | description: Some( | 1606 | description: Some( |
1607 | "struct A", | 1607 | "struct A", |
@@ -1620,7 +1620,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); } | |||
1620 | 22..23, | 1620 | 22..23, |
1621 | ), | 1621 | ), |
1622 | name: "B", | 1622 | name: "B", |
1623 | kind: STRUCT_DEF, | 1623 | kind: STRUCT, |
1624 | container_name: None, | 1624 | container_name: None, |
1625 | description: Some( | 1625 | description: Some( |
1626 | "struct B", | 1626 | "struct B", |
@@ -1639,7 +1639,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); } | |||
1639 | 53..54, | 1639 | 53..54, |
1640 | ), | 1640 | ), |
1641 | name: "C", | 1641 | name: "C", |
1642 | kind: STRUCT_DEF, | 1642 | kind: STRUCT, |
1643 | container_name: None, | 1643 | container_name: None, |
1644 | description: Some( | 1644 | description: Some( |
1645 | "pub struct C", | 1645 | "pub struct C", |
@@ -1678,7 +1678,7 @@ fn main() { let s<|>t = foo(); } | |||
1678 | 6..9, | 1678 | 6..9, |
1679 | ), | 1679 | ), |
1680 | name: "Foo", | 1680 | name: "Foo", |
1681 | kind: TRAIT_DEF, | 1681 | kind: TRAIT, |
1682 | container_name: None, | 1682 | container_name: None, |
1683 | description: Some( | 1683 | description: Some( |
1684 | "trait Foo", | 1684 | "trait Foo", |
@@ -1718,7 +1718,7 @@ fn main() { let s<|>t = foo(); } | |||
1718 | 6..9, | 1718 | 6..9, |
1719 | ), | 1719 | ), |
1720 | name: "Foo", | 1720 | name: "Foo", |
1721 | kind: TRAIT_DEF, | 1721 | kind: TRAIT, |
1722 | container_name: None, | 1722 | container_name: None, |
1723 | description: Some( | 1723 | description: Some( |
1724 | "trait Foo", | 1724 | "trait Foo", |
@@ -1737,7 +1737,7 @@ fn main() { let s<|>t = foo(); } | |||
1737 | 23..24, | 1737 | 23..24, |
1738 | ), | 1738 | ), |
1739 | name: "S", | 1739 | name: "S", |
1740 | kind: STRUCT_DEF, | 1740 | kind: STRUCT, |
1741 | container_name: None, | 1741 | container_name: None, |
1742 | description: Some( | 1742 | description: Some( |
1743 | "struct S", | 1743 | "struct S", |
@@ -1777,7 +1777,7 @@ fn main() { let s<|>t = foo(); } | |||
1777 | 6..9, | 1777 | 6..9, |
1778 | ), | 1778 | ), |
1779 | name: "Foo", | 1779 | name: "Foo", |
1780 | kind: TRAIT_DEF, | 1780 | kind: TRAIT, |
1781 | container_name: None, | 1781 | container_name: None, |
1782 | description: Some( | 1782 | description: Some( |
1783 | "trait Foo", | 1783 | "trait Foo", |
@@ -1796,7 +1796,7 @@ fn main() { let s<|>t = foo(); } | |||
1796 | 19..22, | 1796 | 19..22, |
1797 | ), | 1797 | ), |
1798 | name: "Bar", | 1798 | name: "Bar", |
1799 | kind: TRAIT_DEF, | 1799 | kind: TRAIT, |
1800 | container_name: None, | 1800 | container_name: None, |
1801 | description: Some( | 1801 | description: Some( |
1802 | "trait Bar", | 1802 | "trait Bar", |
@@ -1839,7 +1839,7 @@ fn main() { let s<|>t = foo(); } | |||
1839 | 6..9, | 1839 | 6..9, |
1840 | ), | 1840 | ), |
1841 | name: "Foo", | 1841 | name: "Foo", |
1842 | kind: TRAIT_DEF, | 1842 | kind: TRAIT, |
1843 | container_name: None, | 1843 | container_name: None, |
1844 | description: Some( | 1844 | description: Some( |
1845 | "trait Foo", | 1845 | "trait Foo", |
@@ -1858,7 +1858,7 @@ fn main() { let s<|>t = foo(); } | |||
1858 | 22..25, | 1858 | 22..25, |
1859 | ), | 1859 | ), |
1860 | name: "Bar", | 1860 | name: "Bar", |
1861 | kind: TRAIT_DEF, | 1861 | kind: TRAIT, |
1862 | container_name: None, | 1862 | container_name: None, |
1863 | description: Some( | 1863 | description: Some( |
1864 | "trait Bar", | 1864 | "trait Bar", |
@@ -1877,7 +1877,7 @@ fn main() { let s<|>t = foo(); } | |||
1877 | 39..41, | 1877 | 39..41, |
1878 | ), | 1878 | ), |
1879 | name: "S1", | 1879 | name: "S1", |
1880 | kind: STRUCT_DEF, | 1880 | kind: STRUCT, |
1881 | container_name: None, | 1881 | container_name: None, |
1882 | description: Some( | 1882 | description: Some( |
1883 | "struct S1", | 1883 | "struct S1", |
@@ -1896,7 +1896,7 @@ fn main() { let s<|>t = foo(); } | |||
1896 | 52..54, | 1896 | 52..54, |
1897 | ), | 1897 | ), |
1898 | name: "S2", | 1898 | name: "S2", |
1899 | kind: STRUCT_DEF, | 1899 | kind: STRUCT, |
1900 | container_name: None, | 1900 | container_name: None, |
1901 | description: Some( | 1901 | description: Some( |
1902 | "struct S2", | 1902 | "struct S2", |
@@ -1933,7 +1933,7 @@ fn foo(ar<|>g: &impl Foo) {} | |||
1933 | 6..9, | 1933 | 6..9, |
1934 | ), | 1934 | ), |
1935 | name: "Foo", | 1935 | name: "Foo", |
1936 | kind: TRAIT_DEF, | 1936 | kind: TRAIT, |
1937 | container_name: None, | 1937 | container_name: None, |
1938 | description: Some( | 1938 | description: Some( |
1939 | "trait Foo", | 1939 | "trait Foo", |
@@ -1973,7 +1973,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {} | |||
1973 | 6..9, | 1973 | 6..9, |
1974 | ), | 1974 | ), |
1975 | name: "Foo", | 1975 | name: "Foo", |
1976 | kind: TRAIT_DEF, | 1976 | kind: TRAIT, |
1977 | container_name: None, | 1977 | container_name: None, |
1978 | description: Some( | 1978 | description: Some( |
1979 | "trait Foo", | 1979 | "trait Foo", |
@@ -1992,7 +1992,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {} | |||
1992 | 19..22, | 1992 | 19..22, |
1993 | ), | 1993 | ), |
1994 | name: "Bar", | 1994 | name: "Bar", |
1995 | kind: TRAIT_DEF, | 1995 | kind: TRAIT, |
1996 | container_name: None, | 1996 | container_name: None, |
1997 | description: Some( | 1997 | description: Some( |
1998 | "trait Bar", | 1998 | "trait Bar", |
@@ -2011,7 +2011,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {} | |||
2011 | 36..37, | 2011 | 36..37, |
2012 | ), | 2012 | ), |
2013 | name: "S", | 2013 | name: "S", |
2014 | kind: STRUCT_DEF, | 2014 | kind: STRUCT, |
2015 | container_name: None, | 2015 | container_name: None, |
2016 | description: Some( | 2016 | description: Some( |
2017 | "struct S", | 2017 | "struct S", |
@@ -2049,7 +2049,7 @@ fn foo(ar<|>g: &impl Foo<S>) {} | |||
2049 | 6..9, | 2049 | 6..9, |
2050 | ), | 2050 | ), |
2051 | name: "Foo", | 2051 | name: "Foo", |
2052 | kind: TRAIT_DEF, | 2052 | kind: TRAIT, |
2053 | container_name: None, | 2053 | container_name: None, |
2054 | description: Some( | 2054 | description: Some( |
2055 | "trait Foo", | 2055 | "trait Foo", |
@@ -2068,7 +2068,7 @@ fn foo(ar<|>g: &impl Foo<S>) {} | |||
2068 | 23..24, | 2068 | 23..24, |
2069 | ), | 2069 | ), |
2070 | name: "S", | 2070 | name: "S", |
2071 | kind: STRUCT_DEF, | 2071 | kind: STRUCT, |
2072 | container_name: None, | 2072 | container_name: None, |
2073 | description: Some( | 2073 | description: Some( |
2074 | "struct S", | 2074 | "struct S", |
@@ -2111,7 +2111,7 @@ fn main() { let s<|>t = foo(); } | |||
2111 | 49..50, | 2111 | 49..50, |
2112 | ), | 2112 | ), |
2113 | name: "B", | 2113 | name: "B", |
2114 | kind: STRUCT_DEF, | 2114 | kind: STRUCT, |
2115 | container_name: None, | 2115 | container_name: None, |
2116 | description: Some( | 2116 | description: Some( |
2117 | "struct B", | 2117 | "struct B", |
@@ -2130,7 +2130,7 @@ fn main() { let s<|>t = foo(); } | |||
2130 | 6..9, | 2130 | 6..9, |
2131 | ), | 2131 | ), |
2132 | name: "Foo", | 2132 | name: "Foo", |
2133 | kind: TRAIT_DEF, | 2133 | kind: TRAIT, |
2134 | container_name: None, | 2134 | container_name: None, |
2135 | description: Some( | 2135 | description: Some( |
2136 | "trait Foo", | 2136 | "trait Foo", |
@@ -2167,7 +2167,7 @@ fn foo(ar<|>g: &dyn Foo) {} | |||
2167 | 6..9, | 2167 | 6..9, |
2168 | ), | 2168 | ), |
2169 | name: "Foo", | 2169 | name: "Foo", |
2170 | kind: TRAIT_DEF, | 2170 | kind: TRAIT, |
2171 | container_name: None, | 2171 | container_name: None, |
2172 | description: Some( | 2172 | description: Some( |
2173 | "trait Foo", | 2173 | "trait Foo", |
@@ -2205,7 +2205,7 @@ fn foo(ar<|>g: &dyn Foo<S>) {} | |||
2205 | 6..9, | 2205 | 6..9, |
2206 | ), | 2206 | ), |
2207 | name: "Foo", | 2207 | name: "Foo", |
2208 | kind: TRAIT_DEF, | 2208 | kind: TRAIT, |
2209 | container_name: None, | 2209 | container_name: None, |
2210 | description: Some( | 2210 | description: Some( |
2211 | "trait Foo", | 2211 | "trait Foo", |
@@ -2224,7 +2224,7 @@ fn foo(ar<|>g: &dyn Foo<S>) {} | |||
2224 | 23..24, | 2224 | 23..24, |
2225 | ), | 2225 | ), |
2226 | name: "S", | 2226 | name: "S", |
2227 | kind: STRUCT_DEF, | 2227 | kind: STRUCT, |
2228 | container_name: None, | 2228 | container_name: None, |
2229 | description: Some( | 2229 | description: Some( |
2230 | "struct S", | 2230 | "struct S", |
@@ -2265,7 +2265,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} | |||
2265 | 6..15, | 2265 | 6..15, |
2266 | ), | 2266 | ), |
2267 | name: "ImplTrait", | 2267 | name: "ImplTrait", |
2268 | kind: TRAIT_DEF, | 2268 | kind: TRAIT, |
2269 | container_name: None, | 2269 | container_name: None, |
2270 | description: Some( | 2270 | description: Some( |
2271 | "trait ImplTrait", | 2271 | "trait ImplTrait", |
@@ -2284,7 +2284,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} | |||
2284 | 50..51, | 2284 | 50..51, |
2285 | ), | 2285 | ), |
2286 | name: "B", | 2286 | name: "B", |
2287 | kind: STRUCT_DEF, | 2287 | kind: STRUCT, |
2288 | container_name: None, | 2288 | container_name: None, |
2289 | description: Some( | 2289 | description: Some( |
2290 | "struct B", | 2290 | "struct B", |
@@ -2303,7 +2303,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} | |||
2303 | 28..36, | 2303 | 28..36, |
2304 | ), | 2304 | ), |
2305 | name: "DynTrait", | 2305 | name: "DynTrait", |
2306 | kind: TRAIT_DEF, | 2306 | kind: TRAIT, |
2307 | container_name: None, | 2307 | container_name: None, |
2308 | description: Some( | 2308 | description: Some( |
2309 | "trait DynTrait", | 2309 | "trait DynTrait", |
@@ -2322,7 +2322,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} | |||
2322 | 65..66, | 2322 | 65..66, |
2323 | ), | 2323 | ), |
2324 | name: "S", | 2324 | name: "S", |
2325 | kind: STRUCT_DEF, | 2325 | kind: STRUCT, |
2326 | container_name: None, | 2326 | container_name: None, |
2327 | description: Some( | 2327 | description: Some( |
2328 | "struct S", | 2328 | "struct S", |
@@ -2370,7 +2370,7 @@ fn main() { let s<|>t = test().get(); } | |||
2370 | 6..9, | 2370 | 6..9, |
2371 | ), | 2371 | ), |
2372 | name: "Foo", | 2372 | name: "Foo", |
2373 | kind: TRAIT_DEF, | 2373 | kind: TRAIT, |
2374 | container_name: None, | 2374 | container_name: None, |
2375 | description: Some( | 2375 | description: Some( |
2376 | "trait Foo", | 2376 | "trait Foo", |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index f2e4f7ee5..4bbbcd258 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -2,7 +2,7 @@ use hir::{Adt, Callable, HirDisplay, Semantics, Type}; | |||
2 | use ra_ide_db::RootDatabase; | 2 | use ra_ide_db::RootDatabase; |
3 | use ra_prof::profile; | 3 | use ra_prof::profile; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, | 5 | ast::{self, ArgListOwner, AstNode}, |
6 | match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T, | 6 | match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T, |
7 | }; | 7 | }; |
8 | use stdx::to_lower_snake_case; | 8 | use stdx::to_lower_snake_case; |
@@ -96,7 +96,7 @@ fn get_chaining_hints( | |||
96 | return None; | 96 | return None; |
97 | } | 97 | } |
98 | 98 | ||
99 | if matches!(expr, ast::Expr::RecordLit(_)) { | 99 | if matches!(expr, ast::Expr::RecordExpr(_)) { |
100 | return None; | 100 | return None; |
101 | } | 101 | } |
102 | 102 | ||
@@ -230,10 +230,10 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ | |||
230 | match_ast! { | 230 | match_ast! { |
231 | match node { | 231 | match node { |
232 | ast::LetStmt(it) => { | 232 | ast::LetStmt(it) => { |
233 | return it.ascribed_type().is_some() | 233 | return it.ty().is_some() |
234 | }, | 234 | }, |
235 | ast::Param(it) => { | 235 | ast::Param(it) => { |
236 | return it.ascribed_type().is_some() | 236 | return it.ty().is_some() |
237 | }, | 237 | }, |
238 | ast::MatchArm(_it) => { | 238 | ast::MatchArm(_it) => { |
239 | return pat_is_enum_variant(db, bind_pat, pat_ty); | 239 | return pat_is_enum_variant(db, bind_pat, pat_ty); |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index dc9192d42..0fede0d87 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -487,8 +487,12 @@ impl Analysis { | |||
487 | } | 487 | } |
488 | 488 | ||
489 | /// Computes the set of diagnostics for the given file. | 489 | /// Computes the set of diagnostics for the given file. |
490 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 490 | pub fn diagnostics( |
491 | self.with_db(|db| diagnostics::diagnostics(db, file_id)) | 491 | &self, |
492 | file_id: FileId, | ||
493 | enable_experimental: bool, | ||
494 | ) -> Cancelable<Vec<Diagnostic>> { | ||
495 | self.with_db(|db| diagnostics::diagnostics(db, file_id, enable_experimental)) | ||
492 | } | 496 | } |
493 | 497 | ||
494 | /// Returns the edit required to rename reference at the position to the new | 498 | /// Returns the edit required to rename reference at the position to the new |
@@ -505,9 +509,11 @@ impl Analysis { | |||
505 | &self, | 509 | &self, |
506 | query: &str, | 510 | query: &str, |
507 | parse_only: bool, | 511 | parse_only: bool, |
512 | position: FilePosition, | ||
513 | selections: Vec<FileRange>, | ||
508 | ) -> Cancelable<Result<SourceChange, SsrError>> { | 514 | ) -> Cancelable<Result<SourceChange, SsrError>> { |
509 | self.with_db(|db| { | 515 | self.with_db(|db| { |
510 | let edits = ssr::parse_search_replace(query, parse_only, db)?; | 516 | let edits = ssr::parse_search_replace(query, parse_only, db, position, selections)?; |
511 | Ok(SourceChange::from(edits)) | 517 | Ok(SourceChange::from(edits)) |
512 | }) | 518 | }) |
513 | } | 519 | } |
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index fe1c074d1..519e4bf1a 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -172,16 +172,16 @@ fn get_struct_def_name_for_struct_literal_search( | |||
172 | if let Some(name) = | 172 | if let Some(name) = |
173 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start()) | 173 | sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start()) |
174 | { | 174 | { |
175 | return name.syntax().ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); | 175 | return name.syntax().ancestors().find_map(ast::Struct::cast).and_then(|l| l.name()); |
176 | } | 176 | } |
177 | if sema | 177 | if sema |
178 | .find_node_at_offset_with_descend::<ast::TypeParamList>( | 178 | .find_node_at_offset_with_descend::<ast::GenericParamList>( |
179 | &syntax, | 179 | &syntax, |
180 | left.text_range().start(), | 180 | left.text_range().start(), |
181 | ) | 181 | ) |
182 | .is_some() | 182 | .is_some() |
183 | { | 183 | { |
184 | return left.ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name()); | 184 | return left.ancestors().find_map(ast::Struct::cast).and_then(|l| l.name()); |
185 | } | 185 | } |
186 | } | 186 | } |
187 | None | 187 | None |
@@ -212,7 +212,7 @@ fn main() { | |||
212 | ); | 212 | ); |
213 | check_result( | 213 | check_result( |
214 | refs, | 214 | refs, |
215 | "Foo STRUCT_DEF FileId(1) 0..26 7..10 Other", | 215 | "Foo STRUCT FileId(1) 0..26 7..10 Other", |
216 | &["FileId(1) 101..104 StructLiteral"], | 216 | &["FileId(1) 101..104 StructLiteral"], |
217 | ); | 217 | ); |
218 | } | 218 | } |
@@ -230,7 +230,7 @@ struct Foo<|> {} | |||
230 | ); | 230 | ); |
231 | check_result( | 231 | check_result( |
232 | refs, | 232 | refs, |
233 | "Foo STRUCT_DEF FileId(1) 0..13 7..10 Other", | 233 | "Foo STRUCT FileId(1) 0..13 7..10 Other", |
234 | &["FileId(1) 41..44 Other", "FileId(1) 54..57 StructLiteral"], | 234 | &["FileId(1) 41..44 Other", "FileId(1) 54..57 StructLiteral"], |
235 | ); | 235 | ); |
236 | } | 236 | } |
@@ -248,7 +248,7 @@ struct Foo<T> <|>{} | |||
248 | ); | 248 | ); |
249 | check_result( | 249 | check_result( |
250 | refs, | 250 | refs, |
251 | "Foo STRUCT_DEF FileId(1) 0..16 7..10 Other", | 251 | "Foo STRUCT FileId(1) 0..16 7..10 Other", |
252 | &["FileId(1) 64..67 StructLiteral"], | 252 | &["FileId(1) 64..67 StructLiteral"], |
253 | ); | 253 | ); |
254 | } | 254 | } |
@@ -267,7 +267,7 @@ fn main() { | |||
267 | ); | 267 | ); |
268 | check_result( | 268 | check_result( |
269 | refs, | 269 | refs, |
270 | "Foo STRUCT_DEF FileId(1) 0..16 7..10 Other", | 270 | "Foo STRUCT FileId(1) 0..16 7..10 Other", |
271 | &["FileId(1) 54..57 StructLiteral"], | 271 | &["FileId(1) 54..57 StructLiteral"], |
272 | ); | 272 | ); |
273 | } | 273 | } |
@@ -361,7 +361,7 @@ fn main(s: Foo) { | |||
361 | ); | 361 | ); |
362 | check_result( | 362 | check_result( |
363 | refs, | 363 | refs, |
364 | "spam RECORD_FIELD_DEF FileId(1) 17..30 21..25 Other", | 364 | "spam RECORD_FIELD FileId(1) 17..30 21..25 Other", |
365 | &["FileId(1) 67..71 Other Read"], | 365 | &["FileId(1) 67..71 Other Read"], |
366 | ); | 366 | ); |
367 | } | 367 | } |
@@ -376,7 +376,7 @@ impl Foo { | |||
376 | } | 376 | } |
377 | "#, | 377 | "#, |
378 | ); | 378 | ); |
379 | check_result(refs, "f FN_DEF FileId(1) 27..43 30..31 Other", &[]); | 379 | check_result(refs, "f FN FileId(1) 27..43 30..31 Other", &[]); |
380 | } | 380 | } |
381 | 381 | ||
382 | #[test] | 382 | #[test] |
@@ -390,7 +390,7 @@ enum Foo { | |||
390 | } | 390 | } |
391 | "#, | 391 | "#, |
392 | ); | 392 | ); |
393 | check_result(refs, "B ENUM_VARIANT FileId(1) 22..23 22..23 Other", &[]); | 393 | check_result(refs, "B VARIANT FileId(1) 22..23 22..23 Other", &[]); |
394 | } | 394 | } |
395 | 395 | ||
396 | #[test] | 396 | #[test] |
@@ -431,7 +431,7 @@ fn f() { | |||
431 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); | 431 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); |
432 | check_result( | 432 | check_result( |
433 | refs, | 433 | refs, |
434 | "Foo STRUCT_DEF FileId(2) 17..51 28..31 Other", | 434 | "Foo STRUCT FileId(2) 17..51 28..31 Other", |
435 | &["FileId(1) 53..56 StructLiteral", "FileId(3) 79..82 StructLiteral"], | 435 | &["FileId(1) 53..56 StructLiteral", "FileId(3) 79..82 StructLiteral"], |
436 | ); | 436 | ); |
437 | } | 437 | } |
@@ -486,7 +486,7 @@ pub(super) struct Foo<|> { | |||
486 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); | 486 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); |
487 | check_result( | 487 | check_result( |
488 | refs, | 488 | refs, |
489 | "Foo STRUCT_DEF FileId(3) 0..41 18..21 Other", | 489 | "Foo STRUCT FileId(3) 0..41 18..21 Other", |
490 | &["FileId(2) 20..23 Other", "FileId(2) 47..50 StructLiteral"], | 490 | &["FileId(2) 20..23 Other", "FileId(2) 47..50 StructLiteral"], |
491 | ); | 491 | ); |
492 | } | 492 | } |
@@ -514,7 +514,7 @@ pub(super) struct Foo<|> { | |||
514 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); | 514 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); |
515 | check_result( | 515 | check_result( |
516 | refs, | 516 | refs, |
517 | "quux FN_DEF FileId(1) 19..35 26..30 Other", | 517 | "quux FN FileId(1) 19..35 26..30 Other", |
518 | &["FileId(2) 16..20 StructLiteral", "FileId(3) 16..20 StructLiteral"], | 518 | &["FileId(2) 16..20 StructLiteral", "FileId(3) 16..20 StructLiteral"], |
519 | ); | 519 | ); |
520 | 520 | ||
@@ -522,7 +522,7 @@ pub(super) struct Foo<|> { | |||
522 | analysis.find_all_refs(pos, Some(SearchScope::single_file(bar))).unwrap().unwrap(); | 522 | analysis.find_all_refs(pos, Some(SearchScope::single_file(bar))).unwrap().unwrap(); |
523 | check_result( | 523 | check_result( |
524 | refs, | 524 | refs, |
525 | "quux FN_DEF FileId(1) 19..35 26..30 Other", | 525 | "quux FN FileId(1) 19..35 26..30 Other", |
526 | &["FileId(3) 16..20 StructLiteral"], | 526 | &["FileId(3) 16..20 StructLiteral"], |
527 | ); | 527 | ); |
528 | } | 528 | } |
@@ -580,7 +580,7 @@ fn foo() { | |||
580 | ); | 580 | ); |
581 | check_result( | 581 | check_result( |
582 | refs, | 582 | refs, |
583 | "f RECORD_FIELD_DEF FileId(1) 15..21 15..16 Other", | 583 | "f RECORD_FIELD FileId(1) 15..21 15..16 Other", |
584 | &["FileId(1) 55..56 Other Read", "FileId(1) 68..69 Other Write"], | 584 | &["FileId(1) 55..56 Other Read", "FileId(1) 68..69 Other Write"], |
585 | ); | 585 | ); |
586 | } | 586 | } |
@@ -619,7 +619,7 @@ fn main() { | |||
619 | ); | 619 | ); |
620 | check_result( | 620 | check_result( |
621 | refs, | 621 | refs, |
622 | "new FN_DEF FileId(1) 54..101 61..64 Other", | 622 | "new FN FileId(1) 54..101 61..64 Other", |
623 | &["FileId(1) 146..149 StructLiteral"], | 623 | &["FileId(1) 146..149 StructLiteral"], |
624 | ); | 624 | ); |
625 | } | 625 | } |
@@ -646,7 +646,7 @@ fn main() { | |||
646 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); | 646 | let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); |
647 | check_result( | 647 | check_result( |
648 | refs, | 648 | refs, |
649 | "f FN_DEF FileId(1) 26..35 29..30 Other", | 649 | "f FN FileId(1) 26..35 29..30 Other", |
650 | &["FileId(2) 11..12 Other", "FileId(2) 28..29 StructLiteral"], | 650 | &["FileId(2) 11..12 Other", "FileId(2) 28..29 StructLiteral"], |
651 | ); | 651 | ); |
652 | } | 652 | } |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 8735ec53c..96aed7cc7 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -7,7 +7,8 @@ use ra_ide_db::{ | |||
7 | RootDatabase, | 7 | RootDatabase, |
8 | }; | 8 | }; |
9 | use ra_syntax::{ | 9 | use ra_syntax::{ |
10 | algo::find_node_at_offset, ast, ast::NameOwner, ast::TypeAscriptionOwner, | 10 | algo::find_node_at_offset, |
11 | ast::{self, NameOwner}, | ||
11 | lex_single_valid_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, | 12 | lex_single_valid_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, |
12 | }; | 13 | }; |
13 | use ra_text_edit::TextEdit; | 14 | use ra_text_edit::TextEdit; |
@@ -149,14 +150,14 @@ fn rename_to_self( | |||
149 | let source_file = sema.parse(position.file_id); | 150 | let source_file = sema.parse(position.file_id); |
150 | let syn = source_file.syntax(); | 151 | let syn = source_file.syntax(); |
151 | 152 | ||
152 | let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?; | 153 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)?; |
153 | let params = fn_def.param_list()?; | 154 | let params = fn_def.param_list()?; |
154 | if params.self_param().is_some() { | 155 | if params.self_param().is_some() { |
155 | return None; // method already has self param | 156 | return None; // method already has self param |
156 | } | 157 | } |
157 | let first_param = params.params().next()?; | 158 | let first_param = params.params().next()?; |
158 | let mutable = match first_param.ascribed_type() { | 159 | let mutable = match first_param.ty() { |
159 | Some(ast::TypeRef::ReferenceType(rt)) => rt.mut_token().is_some(), | 160 | Some(ast::Type::ReferenceType(rt)) => rt.mut_token().is_some(), |
160 | _ => return None, // not renaming other types | 161 | _ => return None, // not renaming other types |
161 | }; | 162 | }; |
162 | 163 | ||
@@ -192,15 +193,14 @@ fn text_edit_from_self_param( | |||
192 | self_param: &ast::SelfParam, | 193 | self_param: &ast::SelfParam, |
193 | new_name: &str, | 194 | new_name: &str, |
194 | ) -> Option<TextEdit> { | 195 | ) -> Option<TextEdit> { |
195 | fn target_type_name(impl_def: &ast::ImplDef) -> Option<String> { | 196 | fn target_type_name(impl_def: &ast::Impl) -> Option<String> { |
196 | if let Some(ast::TypeRef::PathType(p)) = impl_def.target_type() { | 197 | if let Some(ast::Type::PathType(p)) = impl_def.target_type() { |
197 | return Some(p.path()?.segment()?.name_ref()?.text().to_string()); | 198 | return Some(p.path()?.segment()?.name_ref()?.text().to_string()); |
198 | } | 199 | } |
199 | None | 200 | None |
200 | } | 201 | } |
201 | 202 | ||
202 | let impl_def = | 203 | let impl_def = find_node_at_offset::<ast::Impl>(syn, self_param.syntax().text_range().start())?; |
203 | find_node_at_offset::<ast::ImplDef>(syn, self_param.syntax().text_range().start())?; | ||
204 | let type_name = target_type_name(&impl_def)?; | 204 | let type_name = target_type_name(&impl_def)?; |
205 | 205 | ||
206 | let mut replacement_text = String::from(new_name); | 206 | let mut replacement_text = String::from(new_name); |
@@ -221,7 +221,7 @@ fn rename_self_to_param( | |||
221 | let syn = source_file.syntax(); | 221 | let syn = source_file.syntax(); |
222 | 222 | ||
223 | let text = sema.db.file_text(position.file_id); | 223 | let text = sema.db.file_text(position.file_id); |
224 | let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?; | 224 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)?; |
225 | let search_range = fn_def.syntax().text_range(); | 225 | let search_range = fn_def.syntax().text_range(); |
226 | 226 | ||
227 | let mut edits: Vec<SourceFileEdit> = vec![]; | 227 | let mut edits: Vec<SourceFileEdit> = vec![]; |
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 95a35a28d..3b7162b84 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -102,7 +102,7 @@ pub(crate) fn runnable( | |||
102 | ) -> Option<Runnable> { | 102 | ) -> Option<Runnable> { |
103 | match_ast! { | 103 | match_ast! { |
104 | match item { | 104 | match item { |
105 | ast::FnDef(it) => runnable_fn(sema, it, file_id), | 105 | ast::Fn(it) => runnable_fn(sema, it, file_id), |
106 | ast::Module(it) => runnable_mod(sema, it, file_id), | 106 | ast::Module(it) => runnable_mod(sema, it, file_id), |
107 | _ => None, | 107 | _ => None, |
108 | } | 108 | } |
@@ -111,7 +111,7 @@ pub(crate) fn runnable( | |||
111 | 111 | ||
112 | fn runnable_fn( | 112 | fn runnable_fn( |
113 | sema: &Semantics<RootDatabase>, | 113 | sema: &Semantics<RootDatabase>, |
114 | fn_def: ast::FnDef, | 114 | fn_def: ast::Fn, |
115 | file_id: FileId, | 115 | file_id: FileId, |
116 | ) -> Option<Runnable> { | 116 | ) -> Option<Runnable> { |
117 | let name_string = fn_def.name()?.text().to_string(); | 117 | let name_string = fn_def.name()?.text().to_string(); |
@@ -188,7 +188,7 @@ pub struct TestAttr { | |||
188 | } | 188 | } |
189 | 189 | ||
190 | impl TestAttr { | 190 | impl TestAttr { |
191 | fn from_fn(fn_def: &ast::FnDef) -> TestAttr { | 191 | fn from_fn(fn_def: &ast::Fn) -> TestAttr { |
192 | let ignore = fn_def | 192 | let ignore = fn_def |
193 | .attrs() | 193 | .attrs() |
194 | .filter_map(|attr| attr.simple_name()) | 194 | .filter_map(|attr| attr.simple_name()) |
@@ -203,7 +203,7 @@ impl TestAttr { | |||
203 | /// | 203 | /// |
204 | /// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test, | 204 | /// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test, |
205 | /// but it's better than not to have the runnables for the tests at all. | 205 | /// but it's better than not to have the runnables for the tests at all. |
206 | fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool { | 206 | fn has_test_related_attribute(fn_def: &ast::Fn) -> bool { |
207 | fn_def | 207 | fn_def |
208 | .attrs() | 208 | .attrs() |
209 | .filter_map(|attr| attr.path()) | 209 | .filter_map(|attr| attr.path()) |
@@ -211,7 +211,7 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool { | |||
211 | .any(|attribute_text| attribute_text.contains("test")) | 211 | .any(|attribute_text| attribute_text.contains("test")) |
212 | } | 212 | } |
213 | 213 | ||
214 | fn has_doc_test(fn_def: &ast::FnDef) -> bool { | 214 | fn has_doc_test(fn_def: &ast::Fn) -> bool { |
215 | fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```")) | 215 | fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```")) |
216 | } | 216 | } |
217 | 217 | ||
@@ -220,15 +220,7 @@ fn runnable_mod( | |||
220 | module: ast::Module, | 220 | module: ast::Module, |
221 | file_id: FileId, | 221 | file_id: FileId, |
222 | ) -> Option<Runnable> { | 222 | ) -> Option<Runnable> { |
223 | let has_test_function = module | 223 | if !has_test_function_or_multiple_test_submodules(&module) { |
224 | .item_list()? | ||
225 | .items() | ||
226 | .filter_map(|it| match it { | ||
227 | ast::ModuleItem::FnDef(it) => Some(it), | ||
228 | _ => None, | ||
229 | }) | ||
230 | .any(|f| has_test_related_attribute(&f)); | ||
231 | if !has_test_function { | ||
232 | return None; | 224 | return None; |
233 | } | 225 | } |
234 | let module_def = sema.to_def(&module)?; | 226 | let module_def = sema.to_def(&module)?; |
@@ -246,6 +238,34 @@ fn runnable_mod( | |||
246 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) | 238 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) |
247 | } | 239 | } |
248 | 240 | ||
241 | // We could create runnables for modules with number_of_test_submodules > 0, | ||
242 | // but that bloats the runnables for no real benefit, since all tests can be run by the submodule already | ||
243 | fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool { | ||
244 | if let Some(item_list) = module.item_list() { | ||
245 | let mut number_of_test_submodules = 0; | ||
246 | |||
247 | for item in item_list.items() { | ||
248 | match item { | ||
249 | ast::Item::Fn(f) => { | ||
250 | if has_test_related_attribute(&f) { | ||
251 | return true; | ||
252 | } | ||
253 | } | ||
254 | ast::Item::Module(submodule) => { | ||
255 | if has_test_function_or_multiple_test_submodules(&submodule) { | ||
256 | number_of_test_submodules += 1; | ||
257 | } | ||
258 | } | ||
259 | _ => (), | ||
260 | } | ||
261 | } | ||
262 | |||
263 | number_of_test_submodules > 1 | ||
264 | } else { | ||
265 | false | ||
266 | } | ||
267 | } | ||
268 | |||
249 | #[cfg(test)] | 269 | #[cfg(test)] |
250 | mod tests { | 270 | mod tests { |
251 | use expect::{expect, Expect}; | 271 | use expect::{expect, Expect}; |
@@ -300,7 +320,7 @@ fn bench() {} | |||
300 | 4..8, | 320 | 4..8, |
301 | ), | 321 | ), |
302 | name: "main", | 322 | name: "main", |
303 | kind: FN_DEF, | 323 | kind: FN, |
304 | container_name: None, | 324 | container_name: None, |
305 | description: None, | 325 | description: None, |
306 | docs: None, | 326 | docs: None, |
@@ -318,7 +338,7 @@ fn bench() {} | |||
318 | 26..34, | 338 | 26..34, |
319 | ), | 339 | ), |
320 | name: "test_foo", | 340 | name: "test_foo", |
321 | kind: FN_DEF, | 341 | kind: FN, |
322 | container_name: None, | 342 | container_name: None, |
323 | description: None, | 343 | description: None, |
324 | docs: None, | 344 | docs: None, |
@@ -343,7 +363,7 @@ fn bench() {} | |||
343 | 62..70, | 363 | 62..70, |
344 | ), | 364 | ), |
345 | name: "test_foo", | 365 | name: "test_foo", |
346 | kind: FN_DEF, | 366 | kind: FN, |
347 | container_name: None, | 367 | container_name: None, |
348 | description: None, | 368 | description: None, |
349 | docs: None, | 369 | docs: None, |
@@ -368,7 +388,7 @@ fn bench() {} | |||
368 | 89..94, | 388 | 89..94, |
369 | ), | 389 | ), |
370 | name: "bench", | 390 | name: "bench", |
371 | kind: FN_DEF, | 391 | kind: FN, |
372 | container_name: None, | 392 | container_name: None, |
373 | description: None, | 393 | description: None, |
374 | docs: None, | 394 | docs: None, |
@@ -411,7 +431,7 @@ fn foo() {} | |||
411 | 4..8, | 431 | 4..8, |
412 | ), | 432 | ), |
413 | name: "main", | 433 | name: "main", |
414 | kind: FN_DEF, | 434 | kind: FN, |
415 | container_name: None, | 435 | container_name: None, |
416 | description: None, | 436 | description: None, |
417 | docs: None, | 437 | docs: None, |
@@ -427,7 +447,7 @@ fn foo() {} | |||
427 | full_range: 15..57, | 447 | full_range: 15..57, |
428 | focus_range: None, | 448 | focus_range: None, |
429 | name: "foo", | 449 | name: "foo", |
430 | kind: FN_DEF, | 450 | kind: FN, |
431 | container_name: None, | 451 | container_name: None, |
432 | description: None, | 452 | description: None, |
433 | docs: None, | 453 | docs: None, |
@@ -473,7 +493,7 @@ impl Data { | |||
473 | 4..8, | 493 | 4..8, |
474 | ), | 494 | ), |
475 | name: "main", | 495 | name: "main", |
476 | kind: FN_DEF, | 496 | kind: FN, |
477 | container_name: None, | 497 | container_name: None, |
478 | description: None, | 498 | description: None, |
479 | docs: None, | 499 | docs: None, |
@@ -489,7 +509,7 @@ impl Data { | |||
489 | full_range: 44..98, | 509 | full_range: 44..98, |
490 | focus_range: None, | 510 | focus_range: None, |
491 | name: "foo", | 511 | name: "foo", |
492 | kind: FN_DEF, | 512 | kind: FN, |
493 | container_name: None, | 513 | container_name: None, |
494 | description: None, | 514 | description: None, |
495 | docs: None, | 515 | docs: None, |
@@ -550,7 +570,7 @@ mod test_mod { | |||
550 | 35..44, | 570 | 35..44, |
551 | ), | 571 | ), |
552 | name: "test_foo1", | 572 | name: "test_foo1", |
553 | kind: FN_DEF, | 573 | kind: FN, |
554 | container_name: None, | 574 | container_name: None, |
555 | description: None, | 575 | description: None, |
556 | docs: None, | 576 | docs: None, |
@@ -571,19 +591,33 @@ mod test_mod { | |||
571 | } | 591 | } |
572 | 592 | ||
573 | #[test] | 593 | #[test] |
574 | fn test_runnables_one_depth_layer_module() { | 594 | fn only_modules_with_test_functions_or_more_than_one_test_submodule_have_runners() { |
575 | check( | 595 | check( |
576 | r#" | 596 | r#" |
577 | //- /lib.rs | 597 | //- /lib.rs |
578 | <|> | 598 | <|> |
579 | mod foo { | 599 | mod root_tests { |
580 | mod test_mod { | 600 | mod nested_tests_0 { |
581 | #[test] | 601 | mod nested_tests_1 { |
582 | fn test_foo1() {} | 602 | #[test] |
603 | fn nested_test_11() {} | ||
604 | |||
605 | #[test] | ||
606 | fn nested_test_12() {} | ||
607 | } | ||
608 | |||
609 | mod nested_tests_2 { | ||
610 | #[test] | ||
611 | fn nested_test_2() {} | ||
612 | } | ||
613 | |||
614 | mod nested_tests_3 {} | ||
583 | } | 615 | } |
616 | |||
617 | mod nested_tests_4 {} | ||
584 | } | 618 | } |
585 | "#, | 619 | "#, |
586 | &[&TEST, &TEST], | 620 | &[&TEST, &TEST, &TEST, &TEST, &TEST, &TEST], |
587 | expect![[r#" | 621 | expect![[r#" |
588 | [ | 622 | [ |
589 | Runnable { | 623 | Runnable { |
@@ -591,18 +625,18 @@ mod foo { | |||
591 | file_id: FileId( | 625 | file_id: FileId( |
592 | 1, | 626 | 1, |
593 | ), | 627 | ), |
594 | full_range: 15..77, | 628 | full_range: 22..323, |
595 | focus_range: Some( | 629 | focus_range: Some( |
596 | 19..27, | 630 | 26..40, |
597 | ), | 631 | ), |
598 | name: "test_mod", | 632 | name: "nested_tests_0", |
599 | kind: MODULE, | 633 | kind: MODULE, |
600 | container_name: None, | 634 | container_name: None, |
601 | description: None, | 635 | description: None, |
602 | docs: None, | 636 | docs: None, |
603 | }, | 637 | }, |
604 | kind: TestMod { | 638 | kind: TestMod { |
605 | path: "foo::test_mod", | 639 | path: "root_tests::nested_tests_0", |
606 | }, | 640 | }, |
607 | cfg_exprs: [], | 641 | cfg_exprs: [], |
608 | }, | 642 | }, |
@@ -611,19 +645,39 @@ mod foo { | |||
611 | file_id: FileId( | 645 | file_id: FileId( |
612 | 1, | 646 | 1, |
613 | ), | 647 | ), |
614 | full_range: 38..71, | 648 | full_range: 51..192, |
615 | focus_range: Some( | 649 | focus_range: Some( |
616 | 57..66, | 650 | 55..69, |
617 | ), | 651 | ), |
618 | name: "test_foo1", | 652 | name: "nested_tests_1", |
619 | kind: FN_DEF, | 653 | kind: MODULE, |
654 | container_name: None, | ||
655 | description: None, | ||
656 | docs: None, | ||
657 | }, | ||
658 | kind: TestMod { | ||
659 | path: "root_tests::nested_tests_0::nested_tests_1", | ||
660 | }, | ||
661 | cfg_exprs: [], | ||
662 | }, | ||
663 | Runnable { | ||
664 | nav: NavigationTarget { | ||
665 | file_id: FileId( | ||
666 | 1, | ||
667 | ), | ||
668 | full_range: 84..126, | ||
669 | focus_range: Some( | ||
670 | 107..121, | ||
671 | ), | ||
672 | name: "nested_test_11", | ||
673 | kind: FN, | ||
620 | container_name: None, | 674 | container_name: None, |
621 | description: None, | 675 | description: None, |
622 | docs: None, | 676 | docs: None, |
623 | }, | 677 | }, |
624 | kind: Test { | 678 | kind: Test { |
625 | test_id: Path( | 679 | test_id: Path( |
626 | "foo::test_mod::test_foo1", | 680 | "root_tests::nested_tests_0::nested_tests_1::nested_test_11", |
627 | ), | 681 | ), |
628 | attr: TestAttr { | 682 | attr: TestAttr { |
629 | ignore: false, | 683 | ignore: false, |
@@ -631,46 +685,48 @@ mod foo { | |||
631 | }, | 685 | }, |
632 | cfg_exprs: [], | 686 | cfg_exprs: [], |
633 | }, | 687 | }, |
634 | ] | ||
635 | "#]], | ||
636 | ); | ||
637 | } | ||
638 | |||
639 | #[test] | ||
640 | fn test_runnables_multiple_depth_module() { | ||
641 | check( | ||
642 | r#" | ||
643 | //- /lib.rs | ||
644 | <|> | ||
645 | mod foo { | ||
646 | mod bar { | ||
647 | mod test_mod { | ||
648 | #[test] | ||
649 | fn test_foo1() {} | ||
650 | } | ||
651 | } | ||
652 | } | ||
653 | "#, | ||
654 | &[&TEST, &TEST], | ||
655 | expect![[r#" | ||
656 | [ | ||
657 | Runnable { | 688 | Runnable { |
658 | nav: NavigationTarget { | 689 | nav: NavigationTarget { |
659 | file_id: FileId( | 690 | file_id: FileId( |
660 | 1, | 691 | 1, |
661 | ), | 692 | ), |
662 | full_range: 33..107, | 693 | full_range: 140..182, |
663 | focus_range: Some( | 694 | focus_range: Some( |
664 | 37..45, | 695 | 163..177, |
665 | ), | 696 | ), |
666 | name: "test_mod", | 697 | name: "nested_test_12", |
698 | kind: FN, | ||
699 | container_name: None, | ||
700 | description: None, | ||
701 | docs: None, | ||
702 | }, | ||
703 | kind: Test { | ||
704 | test_id: Path( | ||
705 | "root_tests::nested_tests_0::nested_tests_1::nested_test_12", | ||
706 | ), | ||
707 | attr: TestAttr { | ||
708 | ignore: false, | ||
709 | }, | ||
710 | }, | ||
711 | cfg_exprs: [], | ||
712 | }, | ||
713 | Runnable { | ||
714 | nav: NavigationTarget { | ||
715 | file_id: FileId( | ||
716 | 1, | ||
717 | ), | ||
718 | full_range: 202..286, | ||
719 | focus_range: Some( | ||
720 | 206..220, | ||
721 | ), | ||
722 | name: "nested_tests_2", | ||
667 | kind: MODULE, | 723 | kind: MODULE, |
668 | container_name: None, | 724 | container_name: None, |
669 | description: None, | 725 | description: None, |
670 | docs: None, | 726 | docs: None, |
671 | }, | 727 | }, |
672 | kind: TestMod { | 728 | kind: TestMod { |
673 | path: "foo::bar::test_mod", | 729 | path: "root_tests::nested_tests_0::nested_tests_2", |
674 | }, | 730 | }, |
675 | cfg_exprs: [], | 731 | cfg_exprs: [], |
676 | }, | 732 | }, |
@@ -679,19 +735,19 @@ mod foo { | |||
679 | file_id: FileId( | 735 | file_id: FileId( |
680 | 1, | 736 | 1, |
681 | ), | 737 | ), |
682 | full_range: 60..97, | 738 | full_range: 235..276, |
683 | focus_range: Some( | 739 | focus_range: Some( |
684 | 83..92, | 740 | 258..271, |
685 | ), | 741 | ), |
686 | name: "test_foo1", | 742 | name: "nested_test_2", |
687 | kind: FN_DEF, | 743 | kind: FN, |
688 | container_name: None, | 744 | container_name: None, |
689 | description: None, | 745 | description: None, |
690 | docs: None, | 746 | docs: None, |
691 | }, | 747 | }, |
692 | kind: Test { | 748 | kind: Test { |
693 | test_id: Path( | 749 | test_id: Path( |
694 | "foo::bar::test_mod::test_foo1", | 750 | "root_tests::nested_tests_0::nested_tests_2::nested_test_2", |
695 | ), | 751 | ), |
696 | attr: TestAttr { | 752 | attr: TestAttr { |
697 | ignore: false, | 753 | ignore: false, |
@@ -727,7 +783,7 @@ fn test_foo1() {} | |||
727 | 36..45, | 783 | 36..45, |
728 | ), | 784 | ), |
729 | name: "test_foo1", | 785 | name: "test_foo1", |
730 | kind: FN_DEF, | 786 | kind: FN, |
731 | container_name: None, | 787 | container_name: None, |
732 | description: None, | 788 | description: None, |
733 | docs: None, | 789 | docs: None, |
@@ -775,7 +831,7 @@ fn test_foo1() {} | |||
775 | 58..67, | 831 | 58..67, |
776 | ), | 832 | ), |
777 | name: "test_foo1", | 833 | name: "test_foo1", |
778 | kind: FN_DEF, | 834 | kind: FN, |
779 | container_name: None, | 835 | container_name: None, |
780 | description: None, | 836 | description: None, |
781 | docs: None, | 837 | docs: None, |
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index b3e9e5dfe..4348b43be 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ra_db::SourceDatabaseExt; | 1 | use ra_db::{FilePosition, FileRange}; |
2 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; | 2 | use ra_ide_db::RootDatabase; |
3 | 3 | ||
4 | use crate::SourceFileEdit; | 4 | use crate::SourceFileEdit; |
5 | use ra_ssr::{MatchFinder, SsrError, SsrRule}; | 5 | use ra_ssr::{MatchFinder, SsrError, SsrRule}; |
@@ -11,6 +11,22 @@ use ra_ssr::{MatchFinder, SsrError, SsrRule}; | |||
11 | // A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement. | 11 | // A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement. |
12 | // Within a macro call, a placeholder will match up until whatever token follows the placeholder. | 12 | // Within a macro call, a placeholder will match up until whatever token follows the placeholder. |
13 | // | 13 | // |
14 | // All paths in both the search pattern and the replacement template must resolve in the context | ||
15 | // in which this command is invoked. Paths in the search pattern will then match the code if they | ||
16 | // resolve to the same item, even if they're written differently. For example if we invoke the | ||
17 | // command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers | ||
18 | // to `foo::Bar` will match. | ||
19 | // | ||
20 | // Paths in the replacement template will be rendered appropriately for the context in which the | ||
21 | // replacement occurs. For example if our replacement template is `foo::Bar` and we match some | ||
22 | // code in the `foo` module, we'll insert just `Bar`. | ||
23 | // | ||
24 | // Method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will match | ||
25 | // `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`. | ||
26 | // | ||
27 | // The scope of the search / replace will be restricted to the current selection if any, otherwise | ||
28 | // it will apply to the whole workspace. | ||
29 | // | ||
14 | // Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`. | 30 | // Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`. |
15 | // | 31 | // |
16 | // Supported constraints: | 32 | // Supported constraints: |
@@ -43,21 +59,14 @@ pub fn parse_search_replace( | |||
43 | rule: &str, | 59 | rule: &str, |
44 | parse_only: bool, | 60 | parse_only: bool, |
45 | db: &RootDatabase, | 61 | db: &RootDatabase, |
62 | resolve_context: FilePosition, | ||
63 | selections: Vec<FileRange>, | ||
46 | ) -> Result<Vec<SourceFileEdit>, SsrError> { | 64 | ) -> Result<Vec<SourceFileEdit>, SsrError> { |
47 | let mut edits = vec![]; | ||
48 | let rule: SsrRule = rule.parse()?; | 65 | let rule: SsrRule = rule.parse()?; |
66 | let mut match_finder = MatchFinder::in_context(db, resolve_context, selections); | ||
67 | match_finder.add_rule(rule)?; | ||
49 | if parse_only { | 68 | if parse_only { |
50 | return Ok(edits); | 69 | return Ok(Vec::new()); |
51 | } | ||
52 | let mut match_finder = MatchFinder::new(db); | ||
53 | match_finder.add_rule(rule); | ||
54 | for &root in db.local_roots().iter() { | ||
55 | let sr = db.source_root(root); | ||
56 | for file_id in sr.iter() { | ||
57 | if let Some(edit) = match_finder.edits_for_file(file_id) { | ||
58 | edits.push(SourceFileEdit { file_id, edit }); | ||
59 | } | ||
60 | } | ||
61 | } | 70 | } |
62 | Ok(edits) | 71 | Ok(match_finder.edits()) |
63 | } | 72 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index d456d5d36..e3a96f9d5 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -464,7 +464,7 @@ fn highlight_element( | |||
464 | let db = sema.db; | 464 | let db = sema.db; |
465 | let mut binding_hash = None; | 465 | let mut binding_hash = None; |
466 | let highlight: Highlight = match element.kind() { | 466 | let highlight: Highlight = match element.kind() { |
467 | FN_DEF => { | 467 | FN => { |
468 | bindings_shadow_count.clear(); | 468 | bindings_shadow_count.clear(); |
469 | return None; | 469 | return None; |
470 | } | 470 | } |
@@ -647,7 +647,7 @@ fn highlight_element( | |||
647 | 647 | ||
648 | fn is_child_of_impl(element: &SyntaxElement) -> bool { | 648 | fn is_child_of_impl(element: &SyntaxElement) -> bool { |
649 | match element.parent() { | 649 | match element.parent() { |
650 | Some(e) => e.kind() == IMPL_DEF, | 650 | Some(e) => e.kind() == IMPL, |
651 | _ => false, | 651 | _ => false, |
652 | } | 652 | } |
653 | } | 653 | } |
@@ -705,18 +705,18 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
705 | }; | 705 | }; |
706 | 706 | ||
707 | let tag = match parent.kind() { | 707 | let tag = match parent.kind() { |
708 | STRUCT_DEF => HighlightTag::Struct, | 708 | STRUCT => HighlightTag::Struct, |
709 | ENUM_DEF => HighlightTag::Enum, | 709 | ENUM => HighlightTag::Enum, |
710 | UNION_DEF => HighlightTag::Union, | 710 | UNION => HighlightTag::Union, |
711 | TRAIT_DEF => HighlightTag::Trait, | 711 | TRAIT => HighlightTag::Trait, |
712 | TYPE_ALIAS_DEF => HighlightTag::TypeAlias, | 712 | TYPE_ALIAS => HighlightTag::TypeAlias, |
713 | TYPE_PARAM => HighlightTag::TypeParam, | 713 | TYPE_PARAM => HighlightTag::TypeParam, |
714 | RECORD_FIELD_DEF => HighlightTag::Field, | 714 | RECORD_FIELD => HighlightTag::Field, |
715 | MODULE => HighlightTag::Module, | 715 | MODULE => HighlightTag::Module, |
716 | FN_DEF => HighlightTag::Function, | 716 | FN => HighlightTag::Function, |
717 | CONST_DEF => HighlightTag::Constant, | 717 | CONST => HighlightTag::Constant, |
718 | STATIC_DEF => HighlightTag::Static, | 718 | STATIC => HighlightTag::Static, |
719 | ENUM_VARIANT => HighlightTag::EnumVariant, | 719 | VARIANT => HighlightTag::EnumVariant, |
720 | BIND_PAT => HighlightTag::Local, | 720 | BIND_PAT => HighlightTag::Local, |
721 | _ => default, | 721 | _ => default, |
722 | }; | 722 | }; |
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs index 0be55bca9..a5e7d2867 100644 --- a/crates/ra_ide/src/syntax_highlighting/html.rs +++ b/crates/ra_ide/src/syntax_highlighting/html.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | //! Renders a bit of code as HTML. | 1 | //! Renders a bit of code as HTML. |
2 | 2 | ||
3 | use oorandom::Rand32; | ||
3 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
4 | use ra_syntax::{AstNode, TextRange, TextSize}; | 5 | use ra_syntax::{AstNode, TextRange, TextSize}; |
5 | 6 | ||
@@ -9,13 +10,12 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
9 | let parse = db.parse(file_id); | 10 | let parse = db.parse(file_id); |
10 | 11 | ||
11 | fn rainbowify(seed: u64) -> String { | 12 | fn rainbowify(seed: u64) -> String { |
12 | use rand::prelude::*; | 13 | let mut rng = Rand32::new(seed); |
13 | let mut rng = SmallRng::seed_from_u64(seed); | ||
14 | format!( | 14 | format!( |
15 | "hsl({h},{s}%,{l}%)", | 15 | "hsl({h},{s}%,{l}%)", |
16 | h = rng.gen_range::<u16, _, _>(0, 361), | 16 | h = rng.rand_range(0..361), |
17 | s = rng.gen_range::<u16, _, _>(42, 99), | 17 | s = rng.rand_range(42..99), |
18 | l = rng.gen_range::<u16, _, _>(40, 91), | 18 | l = rng.rand_range(40..91), |
19 | ) | 19 | ) |
20 | } | 20 | } |
21 | 21 | ||
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index f716a3861..07217e808 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs | |||
@@ -116,7 +116,7 @@ mod tests { | |||
116 | syn.trim(), | 116 | syn.trim(), |
117 | r#" | 117 | r#" |
118 | [email protected] | 118 | [email protected] |
119 | FN_DEF@0..11 | 119 | [email protected] |
120 | [email protected] "fn" | 120 | [email protected] "fn" |
121 | [email protected] " " | 121 | [email protected] " " |
122 | [email protected] | 122 | [email protected] |
@@ -148,7 +148,7 @@ fn test() { | |||
148 | syn.trim(), | 148 | syn.trim(), |
149 | r#" | 149 | r#" |
150 | [email protected] | 150 | [email protected] |
151 | FN_DEF@0..60 | 151 | [email protected] |
152 | [email protected] "fn" | 152 | [email protected] "fn" |
153 | [email protected] " " | 153 | [email protected] " " |
154 | [email protected] | 154 | [email protected] |
@@ -190,7 +190,7 @@ [email protected] | |||
190 | assert_eq_text!( | 190 | assert_eq_text!( |
191 | syn.trim(), | 191 | syn.trim(), |
192 | r#" | 192 | r#" |
193 | FN_DEF@0..11 | 193 | [email protected] |
194 | [email protected] "fn" | 194 | [email protected] "fn" |
195 | [email protected] " " | 195 | [email protected] " " |
196 | [email protected] | 196 | [email protected] |
@@ -258,7 +258,7 @@ fn bar() { | |||
258 | syn.trim(), | 258 | syn.trim(), |
259 | r#" | 259 | r#" |
260 | [email protected] | 260 | [email protected] |
261 | FN_DEF@0..12 | 261 | [email protected] |
262 | [email protected] "fn" | 262 | [email protected] "fn" |
263 | [email protected] " " | 263 | [email protected] " " |
264 | [email protected] | 264 | [email protected] |
@@ -292,7 +292,7 @@ fn bar() { | |||
292 | syn.trim(), | 292 | syn.trim(), |
293 | r#" | 293 | r#" |
294 | [email protected] | 294 | [email protected] |
295 | FN_DEF@0..12 | 295 | [email protected] |
296 | [email protected] "fn" | 296 | [email protected] "fn" |
297 | [email protected] " " | 297 | [email protected] " " |
298 | [email protected] | 298 | [email protected] |
@@ -325,7 +325,7 @@ fn bar() { | |||
325 | syn.trim(), | 325 | syn.trim(), |
326 | r#" | 326 | r#" |
327 | [email protected] | 327 | [email protected] |
328 | FN_DEF@0..12 | 328 | [email protected] |
329 | [email protected] "fn" | 329 | [email protected] "fn" |
330 | [email protected] " " | 330 | [email protected] " " |
331 | [email protected] | 331 | [email protected] |
@@ -339,7 +339,7 @@ [email protected] | |||
339 | [email protected] "\n" | 339 | [email protected] "\n" |
340 | [email protected] "}" | 340 | [email protected] "}" |
341 | [email protected] "\n" | 341 | [email protected] "\n" |
342 | FN_DEF@13..25 | 342 | [email protected] |
343 | [email protected] "fn" | 343 | [email protected] "fn" |
344 | [email protected] " " | 344 | [email protected] " " |
345 | [email protected] | 345 | [email protected] |
diff --git a/crates/ra_ide/test_data/rainbow_highlighting.html b/crates/ra_ide/test_data/rainbow_highlighting.html index 08d83302c..401e87a73 100644 --- a/crates/ra_ide/test_data/rainbow_highlighting.html +++ b/crates/ra_ide/test_data/rainbow_highlighting.html | |||
@@ -36,14 +36,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 36 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
37 | </style> | 37 | </style> |
38 | <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 38 | <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
39 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span> | 39 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span> |
40 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 40 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(76,47%,83%);">x</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
41 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 41 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(15,86%,51%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
42 | 42 | ||
43 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="punctuation">;</span> | 43 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="punctuation">;</span> |
44 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 44 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(90,74%,79%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
45 | <span class="punctuation">}</span> | 45 | <span class="punctuation">}</span> |
46 | 46 | ||
47 | <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 47 | <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
48 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span> | 48 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span> |
49 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 49 | <span class="punctuation">}</span></code></pre> \ No newline at end of file |