aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/handlers/extract_struct_from_enum_variant.rs8
-rw-r--r--crates/assists/src/handlers/fill_match_arms.rs2
-rw-r--r--crates/assists/src/handlers/fix_visibility.rs2
-rw-r--r--crates/assists/src/handlers/generate_function.rs2
-rw-r--r--crates/completion/src/completions.rs10
-rw-r--r--crates/completion/src/completions/attribute.rs16
-rw-r--r--crates/completion/src/completions/dot.rs8
-rw-r--r--crates/completion/src/completions/keyword.rs142
-rw-r--r--crates/completion/src/completions/mod_.rs4
-rw-r--r--crates/completion/src/completions/pattern.rs6
-rw-r--r--crates/completion/src/completions/postfix.rs62
-rw-r--r--crates/completion/src/completions/qualified_path.rs56
-rw-r--r--crates/completion/src/completions/record.rs4
-rw-r--r--crates/completion/src/completions/snippet.rs4
-rw-r--r--crates/completion/src/completions/trait_impl.rs4
-rw-r--r--crates/completion/src/completions/unqualified_path.rs179
-rw-r--r--crates/completion/src/render.rs9
-rw-r--r--crates/completion/src/render/enum_variant.rs26
-rw-r--r--crates/completion/src/render/macro_.rs1
-rw-r--r--crates/completion/src/test_utils.rs3
-rw-r--r--crates/hir/src/attrs.rs6
-rw-r--r--crates/hir/src/code_model.rs57
-rw-r--r--crates/hir/src/from_id.rs23
-rw-r--r--crates/hir/src/has_source.rs6
-rw-r--r--crates/hir/src/lib.rs6
-rw-r--r--crates/hir/src/semantics.rs4
-rw-r--r--crates/hir/src/source_analyzer.rs18
-rw-r--r--crates/hir_def/src/adt.rs47
-rw-r--r--crates/hir_def/src/attr.rs290
-rw-r--r--crates/hir_def/src/body.rs17
-rw-r--r--crates/hir_def/src/body/lower.rs2
-rw-r--r--crates/hir_def/src/data.rs5
-rw-r--r--crates/hir_def/src/item_tree.rs24
-rw-r--r--crates/hir_def/src/item_tree/lower.rs24
-rw-r--r--crates/hir_def/src/lib.rs30
-rw-r--r--crates/hir_def/src/nameres/collector.rs107
-rw-r--r--crates/hir_def/src/nameres/tests.rs4
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs18
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs8
-rw-r--r--crates/hir_def/src/path.rs12
-rw-r--r--crates/hir_expand/src/name.rs2
-rw-r--r--crates/ide/src/call_hierarchy.rs52
-rw-r--r--crates/ide/src/diagnostics/fixes.rs2
-rw-r--r--crates/ide/src/display.rs3
-rw-r--r--crates/ide/src/display/navigation_target.rs247
-rw-r--r--crates/ide/src/doc_links.rs4
-rw-r--r--crates/ide/src/file_structure.rs80
-rw-r--r--crates/ide/src/goto_definition.rs4
-rw-r--r--crates/ide/src/hover.rs448
-rw-r--r--crates/ide/src/lib.rs16
-rw-r--r--crates/ide/src/parent_module.rs6
-rw-r--r--crates/ide/src/references.rs72
-rw-r--r--crates/ide/src/references/rename.rs35
-rw-r--r--crates/ide/src/runnables.rs366
-rw-r--r--crates/ide/src/syntax_highlighting.rs126
-rw-r--r--crates/ide/src/syntax_highlighting/format.rs6
-rw-r--r--crates/ide/src/syntax_highlighting/injection.rs3
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs94
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html12
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html24
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html10
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html36
-rw-r--r--crates/ide_db/src/defs.rs4
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs15
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs14
-rw-r--r--crates/ide_db/src/search.rs2
-rw-r--r--crates/ide_db/src/symbol_index.rs48
-rw-r--r--crates/mbe/src/mbe_expander/transcriber.rs2
-rw-r--r--crates/mbe/src/parser.rs4
-rw-r--r--crates/mbe/src/syntax_bridge.rs3
-rw-r--r--crates/mbe/src/tests.rs12
-rw-r--r--crates/parser/src/grammar.rs4
-rw-r--r--crates/parser/src/lib.rs3
-rw-r--r--crates/project_model/src/cargo_workspace.rs31
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/caps.rs3
-rw-r--r--crates/rust-analyzer/src/handlers.rs19
-rw-r--r--crates/rust-analyzer/src/to_proto.rs114
-rw-r--r--crates/syntax/src/ast/make.rs3
-rw-r--r--crates/syntax/src/lib.rs7
81 files changed, 1691 insertions, 1505 deletions
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
index 2e56bd7ff..030b9cd0c 100644
--- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -1,7 +1,7 @@
1use std::iter; 1use std::iter;
2 2
3use either::Either; 3use either::Either;
4use hir::{AsName, EnumVariant, Module, ModuleDef, Name}; 4use hir::{AsName, Module, ModuleDef, Name, Variant};
5use ide_db::helpers::{ 5use ide_db::helpers::{
6 insert_use::{insert_use, ImportScope}, 6 insert_use::{insert_use, ImportScope},
7 mod_path_to_ast, 7 mod_path_to_ast,
@@ -53,7 +53,7 @@ pub(crate) fn extract_struct_from_enum_variant(
53 let variant_hir_name = variant_hir.name(ctx.db()); 53 let variant_hir_name = variant_hir.name(ctx.db());
54 let enum_module_def = ModuleDef::from(enum_hir); 54 let enum_module_def = ModuleDef::from(enum_hir);
55 let usages = 55 let usages =
56 Definition::ModuleDef(ModuleDef::EnumVariant(variant_hir)).usages(&ctx.sema).all(); 56 Definition::ModuleDef(ModuleDef::Variant(variant_hir)).usages(&ctx.sema).all();
57 57
58 let mut visited_modules_set = FxHashSet::default(); 58 let mut visited_modules_set = FxHashSet::default();
59 let current_module = enum_hir.module(ctx.db()); 59 let current_module = enum_hir.module(ctx.db());
@@ -109,7 +109,7 @@ fn extract_field_list_if_applicable(
109 } 109 }
110} 110}
111 111
112fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &EnumVariant) -> bool { 112fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Variant) -> bool {
113 variant 113 variant
114 .parent_enum(db) 114 .parent_enum(db)
115 .module(db) 115 .module(db)
@@ -119,7 +119,7 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &En
119 // only check type-namespace 119 // only check type-namespace
120 hir::ScopeDef::ModuleDef(def) => matches!(def, 120 hir::ScopeDef::ModuleDef(def) => matches!(def,
121 ModuleDef::Module(_) | ModuleDef::Adt(_) | 121 ModuleDef::Module(_) | ModuleDef::Adt(_) |
122 ModuleDef::EnumVariant(_) | ModuleDef::Trait(_) | 122 ModuleDef::Variant(_) | ModuleDef::Trait(_) |
123 ModuleDef::TypeAlias(_) | ModuleDef::BuiltinType(_) 123 ModuleDef::TypeAlias(_) | ModuleDef::BuiltinType(_)
124 ), 124 ),
125 _ => false, 125 _ => false,
diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs
index ef12ef0cf..cb60a3128 100644
--- a/crates/assists/src/handlers/fill_match_arms.rs
+++ b/crates/assists/src/handlers/fill_match_arms.rs
@@ -192,7 +192,7 @@ fn resolve_tuple_of_enum_def(
192 .collect() 192 .collect()
193} 193}
194 194
195fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> { 195fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::Variant) -> Option<ast::Pat> {
196 let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?); 196 let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
197 197
198 // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though 198 // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
diff --git a/crates/assists/src/handlers/fix_visibility.rs b/crates/assists/src/handlers/fix_visibility.rs
index c86720787..8558a8ff0 100644
--- a/crates/assists/src/handlers/fix_visibility.rs
+++ b/crates/assists/src/handlers/fix_visibility.rs
@@ -201,7 +201,7 @@ fn target_data_for_def(
201 (vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id) 201 (vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id)
202 } 202 }
203 // Enum variants can't be private, we can't modify builtin types 203 // Enum variants can't be private, we can't modify builtin types
204 hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None, 204 hir::ModuleDef::Variant(_) | hir::ModuleDef::BuiltinType(_) => return None,
205 }; 205 };
206 206
207 Some((offset, current_visibility, target, target_file, target_name)) 207 Some((offset, current_visibility, target, target_file, target_name))
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs
index 758188a42..f4cf155b6 100644
--- a/crates/assists/src/handlers/generate_function.rs
+++ b/crates/assists/src/handlers/generate_function.rs
@@ -145,7 +145,7 @@ impl FunctionBuilder {
145 self.type_params, 145 self.type_params,
146 self.params, 146 self.params,
147 fn_body, 147 fn_body,
148 Some(make::ret_type(make::ty("()"))), 148 Some(make::ret_type(make::ty_unit())),
149 ); 149 );
150 let leading_ws; 150 let leading_ws;
151 let trailing_ws; 151 let trailing_ws;
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs
index 9b7d6c580..1ef6b5f48 100644
--- a/crates/completion/src/completions.rs
+++ b/crates/completion/src/completions.rs
@@ -19,7 +19,7 @@ use hir::{ModPath, ScopeDef, Type};
19use crate::{ 19use crate::{
20 item::Builder, 20 item::Builder,
21 render::{ 21 render::{
22 const_::render_const, enum_variant::render_enum_variant, function::render_fn, 22 const_::render_const, enum_variant::render_variant, function::render_fn,
23 macro_::render_macro, render_field, render_resolution, render_tuple_field, 23 macro_::render_macro, render_field, render_resolution, render_tuple_field,
24 type_alias::render_type_alias, RenderContext, 24 type_alias::render_type_alias, RenderContext,
25 }, 25 },
@@ -120,20 +120,20 @@ impl Completions {
120 pub(crate) fn add_qualified_enum_variant( 120 pub(crate) fn add_qualified_enum_variant(
121 &mut self, 121 &mut self,
122 ctx: &CompletionContext, 122 ctx: &CompletionContext,
123 variant: hir::EnumVariant, 123 variant: hir::Variant,
124 path: ModPath, 124 path: ModPath,
125 ) { 125 ) {
126 let item = render_enum_variant(RenderContext::new(ctx), None, None, variant, Some(path)); 126 let item = render_variant(RenderContext::new(ctx), None, None, variant, Some(path));
127 self.add(item); 127 self.add(item);
128 } 128 }
129 129
130 pub(crate) fn add_enum_variant( 130 pub(crate) fn add_enum_variant(
131 &mut self, 131 &mut self,
132 ctx: &CompletionContext, 132 ctx: &CompletionContext,
133 variant: hir::EnumVariant, 133 variant: hir::Variant,
134 local_name: Option<String>, 134 local_name: Option<String>,
135 ) { 135 ) {
136 let item = render_enum_variant(RenderContext::new(ctx), None, local_name, variant, None); 136 let item = render_variant(RenderContext::new(ctx), None, local_name, variant, None);
137 self.add(item); 137 self.add(item);
138 } 138 }
139} 139}
diff --git a/crates/completion/src/completions/attribute.rs b/crates/completion/src/completions/attribute.rs
index acce2e7e7..19ce2482f 100644
--- a/crates/completion/src/completions/attribute.rs
+++ b/crates/completion/src/completions/attribute.rs
@@ -428,8 +428,8 @@ struct Test {}
428 at Hash 428 at Hash
429 at PartialEq 429 at PartialEq
430 at PartialEq, Eq 430 at PartialEq, Eq
431 at PartialEq, Eq, PartialOrd, Ord
432 at PartialEq, PartialOrd 431 at PartialEq, PartialOrd
432 at PartialEq, Eq, PartialOrd, Ord
433 "#]], 433 "#]],
434 ); 434 );
435 } 435 }
@@ -457,10 +457,10 @@ struct Test {}
457 at Clone, Copy 457 at Clone, Copy
458 at Debug 458 at Debug
459 at Default 459 at Default
460 at Eq
461 at Eq, PartialOrd, Ord
462 at Hash 460 at Hash
461 at Eq
463 at PartialOrd 462 at PartialOrd
463 at Eq, PartialOrd, Ord
464 "#]], 464 "#]],
465 ) 465 )
466 } 466 }
@@ -472,14 +472,14 @@ struct Test {}
472 expect![[r#" 472 expect![[r#"
473 at allow(…) 473 at allow(…)
474 at automatically_derived 474 at automatically_derived
475 at cfg(…)
476 at cfg_attr(…) 475 at cfg_attr(…)
476 at cfg(…)
477 at cold 477 at cold
478 at deny(…) 478 at deny(…)
479 at deprecated = "…" 479 at deprecated = "…"
480 at derive(…) 480 at derive(…)
481 at doc = "…"
482 at export_name = "…" 481 at export_name = "…"
482 at doc = "…"
483 at forbid(…) 483 at forbid(…)
484 at ignore = "…" 484 at ignore = "…"
485 at inline(…) 485 at inline(…)
@@ -518,15 +518,15 @@ struct Test {}
518 expect![[r#" 518 expect![[r#"
519 at allow(…) 519 at allow(…)
520 at automatically_derived 520 at automatically_derived
521 at cfg(…)
522 at cfg_attr(…) 521 at cfg_attr(…)
522 at cfg(…)
523 at cold 523 at cold
524 at crate_name = "" 524 at crate_name = ""
525 at deny(…) 525 at deny(…)
526 at deprecated = "…" 526 at deprecated = "…"
527 at derive(…) 527 at derive(…)
528 at doc = "…"
529 at export_name = "…" 528 at export_name = "…"
529 at doc = "…"
530 at feature(…) 530 at feature(…)
531 at forbid(…) 531 at forbid(…)
532 at global_allocator 532 at global_allocator
@@ -538,8 +538,8 @@ struct Test {}
538 at macro_export 538 at macro_export
539 at macro_use 539 at macro_use
540 at must_use = "…" 540 at must_use = "…"
541 at no_implicit_prelude
542 at no_link 541 at no_link
542 at no_implicit_prelude
543 at no_main 543 at no_main
544 at no_mangle 544 at no_mangle
545 at no_std 545 at no_std
diff --git a/crates/completion/src/completions/dot.rs b/crates/completion/src/completions/dot.rs
index c9875045a..551ef1771 100644
--- a/crates/completion/src/completions/dot.rs
+++ b/crates/completion/src/completions/dot.rs
@@ -82,8 +82,8 @@ impl S {
82fn foo(s: S) { s.<|> } 82fn foo(s: S) { s.<|> }
83"#, 83"#,
84 expect![[r#" 84 expect![[r#"
85 me bar() fn bar(&self)
86 fd foo u32 85 fd foo u32
86 me bar() fn bar(&self)
87 "#]], 87 "#]],
88 ); 88 );
89 } 89 }
@@ -98,8 +98,8 @@ impl S {
98} 98}
99"#, 99"#,
100 expect![[r#" 100 expect![[r#"
101 me foo() fn foo(self)
102 fd the_field (u32,) 101 fd the_field (u32,)
102 me foo() fn foo(self)
103 "#]], 103 "#]],
104 ) 104 )
105 } 105 }
@@ -114,8 +114,8 @@ impl A {
114} 114}
115"#, 115"#,
116 expect![[r#" 116 expect![[r#"
117 me foo() fn foo(&self)
118 fd the_field (u32, i32) 117 fd the_field (u32, i32)
118 me foo() fn foo(&self)
119 "#]], 119 "#]],
120 ) 120 )
121 } 121 }
@@ -147,8 +147,8 @@ mod inner {
147fn foo(a: inner::A) { a.<|> } 147fn foo(a: inner::A) { a.<|> }
148"#, 148"#,
149 expect![[r#" 149 expect![[r#"
150 fd crate_field u32
151 fd pub_field u32 150 fd pub_field u32
151 fd crate_field u32
152 fd super_field u32 152 fd super_field u32
153 "#]], 153 "#]],
154 ); 154 );
diff --git a/crates/completion/src/completions/keyword.rs b/crates/completion/src/completions/keyword.rs
index 720349b9d..1859dec70 100644
--- a/crates/completion/src/completions/keyword.rs
+++ b/crates/completion/src/completions/keyword.rs
@@ -223,21 +223,21 @@ mod tests {
223 check( 223 check(
224 r"m<|>", 224 r"m<|>",
225 expect![[r#" 225 expect![[r#"
226 kw const
227 kw enum
228 kw extern
229 kw fn 226 kw fn
227 kw use
230 kw impl 228 kw impl
231 kw mod
232 kw pub
233 kw pub(crate)
234 kw static
235 kw struct
236 kw trait 229 kw trait
237 kw type 230 kw enum
231 kw struct
238 kw union 232 kw union
233 kw mod
234 kw const
235 kw type
236 kw static
237 kw extern
239 kw unsafe 238 kw unsafe
240 kw use 239 kw pub(crate)
240 kw pub
241 "#]], 241 "#]],
242 ); 242 );
243 } 243 }
@@ -247,23 +247,23 @@ mod tests {
247 check( 247 check(
248 r"fn quux() { <|> }", 248 r"fn quux() { <|> }",
249 expect![[r#" 249 expect![[r#"
250 kw const
251 kw extern
252 kw fn 250 kw fn
251 kw use
252 kw impl
253 kw trait
254 kw match
255 kw while
256 kw loop
253 kw if 257 kw if
254 kw if let 258 kw if let
255 kw impl
256 kw let 259 kw let
257 kw loop
258 kw match
259 kw mod 260 kw mod
260 kw return 261 kw const
261 kw static
262 kw trait
263 kw type 262 kw type
263 kw static
264 kw extern
264 kw unsafe 265 kw unsafe
265 kw use 266 kw return
266 kw while
267 "#]], 267 "#]],
268 ); 268 );
269 } 269 }
@@ -273,23 +273,23 @@ mod tests {
273 check( 273 check(
274 r"fn quux() { if true { <|> } }", 274 r"fn quux() { if true { <|> } }",
275 expect![[r#" 275 expect![[r#"
276 kw const
277 kw extern
278 kw fn 276 kw fn
277 kw use
278 kw impl
279 kw trait
280 kw match
281 kw while
282 kw loop
279 kw if 283 kw if
280 kw if let 284 kw if let
281 kw impl
282 kw let 285 kw let
283 kw loop
284 kw match
285 kw mod 286 kw mod
286 kw return 287 kw const
287 kw static
288 kw trait
289 kw type 288 kw type
289 kw static
290 kw extern
290 kw unsafe 291 kw unsafe
291 kw use 292 kw return
292 kw while
293 "#]], 293 "#]],
294 ); 294 );
295 } 295 }
@@ -299,25 +299,25 @@ mod tests {
299 check( 299 check(
300 r#"fn quux() { if true { () } <|> }"#, 300 r#"fn quux() { if true { () } <|> }"#,
301 expect![[r#" 301 expect![[r#"
302 kw const
303 kw else
304 kw else if
305 kw extern
306 kw fn 302 kw fn
303 kw use
304 kw impl
305 kw trait
306 kw match
307 kw while
308 kw loop
307 kw if 309 kw if
308 kw if let 310 kw if let
309 kw impl
310 kw let 311 kw let
311 kw loop 312 kw else
312 kw match 313 kw else if
313 kw mod 314 kw mod
314 kw return 315 kw const
315 kw static
316 kw trait
317 kw type 316 kw type
317 kw static
318 kw extern
318 kw unsafe 319 kw unsafe
319 kw use 320 kw return
320 kw while
321 "#]], 321 "#]],
322 ); 322 );
323 check_edit( 323 check_edit(
@@ -336,13 +336,13 @@ fn quux() -> i32 {
336} 336}
337"#, 337"#,
338 expect![[r#" 338 expect![[r#"
339 kw match
340 kw while
341 kw loop
339 kw if 342 kw if
340 kw if let 343 kw if let
341 kw loop
342 kw match
343 kw return
344 kw unsafe 344 kw unsafe
345 kw while 345 kw return
346 "#]], 346 "#]],
347 ); 347 );
348 } 348 }
@@ -352,8 +352,8 @@ fn quux() -> i32 {
352 check( 352 check(
353 r"trait My { <|> }", 353 r"trait My { <|> }",
354 expect![[r#" 354 expect![[r#"
355 kw const
356 kw fn 355 kw fn
356 kw const
357 kw type 357 kw type
358 kw unsafe 358 kw unsafe
359 "#]], 359 "#]],
@@ -365,12 +365,12 @@ fn quux() -> i32 {
365 check( 365 check(
366 r"impl My { <|> }", 366 r"impl My { <|> }",
367 expect![[r#" 367 expect![[r#"
368 kw const
369 kw fn 368 kw fn
370 kw pub 369 kw const
371 kw pub(crate)
372 kw type 370 kw type
373 kw unsafe 371 kw unsafe
372 kw pub(crate)
373 kw pub
374 "#]], 374 "#]],
375 ); 375 );
376 } 376 }
@@ -380,25 +380,25 @@ fn quux() -> i32 {
380 check( 380 check(
381 r"fn my() { loop { <|> } }", 381 r"fn my() { loop { <|> } }",
382 expect![[r#" 382 expect![[r#"
383 kw break
384 kw const
385 kw continue
386 kw extern
387 kw fn 383 kw fn
384 kw use
385 kw impl
386 kw trait
387 kw match
388 kw while
389 kw loop
388 kw if 390 kw if
389 kw if let 391 kw if let
390 kw impl
391 kw let 392 kw let
392 kw loop
393 kw match
394 kw mod 393 kw mod
395 kw return 394 kw const
396 kw static
397 kw trait
398 kw type 395 kw type
396 kw static
397 kw extern
399 kw unsafe 398 kw unsafe
400 kw use 399 kw continue
401 kw while 400 kw break
401 kw return
402 "#]], 402 "#]],
403 ); 403 );
404 } 404 }
@@ -409,8 +409,8 @@ fn quux() -> i32 {
409 r"unsafe <|>", 409 r"unsafe <|>",
410 expect![[r#" 410 expect![[r#"
411 kw fn 411 kw fn
412 kw impl
413 kw trait 412 kw trait
413 kw impl
414 "#]], 414 "#]],
415 ); 415 );
416 } 416 }
@@ -421,8 +421,8 @@ fn quux() -> i32 {
421 r"fn my_fn() { unsafe <|> }", 421 r"fn my_fn() { unsafe <|> }",
422 expect![[r#" 422 expect![[r#"
423 kw fn 423 kw fn
424 kw impl
425 kw trait 424 kw trait
425 kw impl
426 "#]], 426 "#]],
427 ); 427 );
428 } 428 }
@@ -542,12 +542,12 @@ pub mod future {
542 check( 542 check(
543 r#"fn main() { let _ = <|> }"#, 543 r#"fn main() { let _ = <|> }"#,
544 expect![[r#" 544 expect![[r#"
545 kw match
546 kw while
547 kw loop
545 kw if 548 kw if
546 kw if let 549 kw if let
547 kw loop
548 kw match
549 kw return 550 kw return
550 kw while
551 "#]], 551 "#]],
552 ) 552 )
553 } 553 }
@@ -562,8 +562,8 @@ struct Foo {
562} 562}
563"#, 563"#,
564 expect![[r#" 564 expect![[r#"
565 kw pub
566 kw pub(crate) 565 kw pub(crate)
566 kw pub
567 "#]], 567 "#]],
568 ) 568 )
569 } 569 }
@@ -600,12 +600,12 @@ fn foo() {
600} 600}
601"#, 601"#,
602 expect![[r#" 602 expect![[r#"
603 kw match
604 kw while
605 kw loop
603 kw if 606 kw if
604 kw if let 607 kw if let
605 kw loop
606 kw match
607 kw return 608 kw return
608 kw while
609 "#]], 609 "#]],
610 ); 610 );
611 } 611 }
diff --git a/crates/completion/src/completions/mod_.rs b/crates/completion/src/completions/mod_.rs
index c96f84171..f77864b77 100644
--- a/crates/completion/src/completions/mod_.rs
+++ b/crates/completion/src/completions/mod_.rs
@@ -170,8 +170,8 @@ mod tests {
170 fn ignored_bar() {} 170 fn ignored_bar() {}
171 "#, 171 "#,
172 expect![[r#" 172 expect![[r#"
173 md bar;
174 md foo; 173 md foo;
174 md bar;
175 "#]], 175 "#]],
176 ); 176 );
177 } 177 }
@@ -207,8 +207,8 @@ mod tests {
207 fn ignored_bar() {} 207 fn ignored_bar() {}
208 "#, 208 "#,
209 expect![[r#" 209 expect![[r#"
210 md bar;
211 md foo; 210 md foo;
211 md bar;
212 "#]], 212 "#]],
213 ); 213 );
214 } 214 }
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs
index 4f63ff0ef..4d56731ec 100644
--- a/crates/completion/src/completions/pattern.rs
+++ b/crates/completion/src/completions/pattern.rs
@@ -23,7 +23,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
23 def, 23 def,
24 hir::ModuleDef::Adt(hir::Adt::Enum(..)) 24 hir::ModuleDef::Adt(hir::Adt::Enum(..))
25 | hir::ModuleDef::Adt(hir::Adt::Struct(..)) 25 | hir::ModuleDef::Adt(hir::Adt::Struct(..))
26 | hir::ModuleDef::EnumVariant(..) 26 | hir::ModuleDef::Variant(..)
27 | hir::ModuleDef::Const(..) 27 | hir::ModuleDef::Const(..)
28 | hir::ModuleDef::Module(..) 28 | hir::ModuleDef::Module(..)
29 ) 29 )
@@ -66,10 +66,10 @@ fn foo() {
66} 66}
67"#, 67"#,
68 expect![[r#" 68 expect![[r#"
69 st Bar
70 en E 69 en E
71 ev X ()
72 ct Z 70 ct Z
71 st Bar
72 ev X ()
73 md m 73 md m
74 "#]], 74 "#]],
75 ); 75 );
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs
index c8ba63cd3..d6db82a93 100644
--- a/crates/completion/src/completions/postfix.rs
+++ b/crates/completion/src/completions/postfix.rs
@@ -315,20 +315,20 @@ fn main() {
315} 315}
316"#, 316"#,
317 expect![[r#" 317 expect![[r#"
318 sn box Box::new(expr)
319 sn call function(expr)
320 sn dbg dbg!(expr)
321 sn dbgr dbg!(&expr)
322 sn if if expr {} 318 sn if if expr {}
323 sn let let 319 sn while while expr {}
324 sn letm let mut
325 sn match match expr {}
326 sn not !expr 320 sn not !expr
327 sn ok Ok(expr)
328 sn ref &expr 321 sn ref &expr
329 sn refm &mut expr 322 sn refm &mut expr
323 sn match match expr {}
324 sn box Box::new(expr)
325 sn ok Ok(expr)
330 sn some Some(expr) 326 sn some Some(expr)
331 sn while while expr {} 327 sn dbg dbg!(expr)
328 sn dbgr dbg!(&expr)
329 sn call function(expr)
330 sn let let
331 sn letm let mut
332 "#]], 332 "#]],
333 ); 333 );
334 } 334 }
@@ -347,18 +347,18 @@ fn main() {
347} 347}
348"#, 348"#,
349 expect![[r#" 349 expect![[r#"
350 sn box Box::new(expr)
351 sn call function(expr)
352 sn dbg dbg!(expr)
353 sn dbgr dbg!(&expr)
354 sn if if expr {} 350 sn if if expr {}
355 sn match match expr {} 351 sn while while expr {}
356 sn not !expr 352 sn not !expr
357 sn ok Ok(expr)
358 sn ref &expr 353 sn ref &expr
359 sn refm &mut expr 354 sn refm &mut expr
355 sn match match expr {}
356 sn box Box::new(expr)
357 sn ok Ok(expr)
360 sn some Some(expr) 358 sn some Some(expr)
361 sn while while expr {} 359 sn dbg dbg!(expr)
360 sn dbgr dbg!(&expr)
361 sn call function(expr)
362 "#]], 362 "#]],
363 ); 363 );
364 } 364 }
@@ -373,17 +373,17 @@ fn main() {
373} 373}
374"#, 374"#,
375 expect![[r#" 375 expect![[r#"
376 sn ref &expr
377 sn refm &mut expr
378 sn match match expr {}
376 sn box Box::new(expr) 379 sn box Box::new(expr)
377 sn call function(expr) 380 sn ok Ok(expr)
381 sn some Some(expr)
378 sn dbg dbg!(expr) 382 sn dbg dbg!(expr)
379 sn dbgr dbg!(&expr) 383 sn dbgr dbg!(&expr)
384 sn call function(expr)
380 sn let let 385 sn let let
381 sn letm let mut 386 sn letm let mut
382 sn match match expr {}
383 sn ok Ok(expr)
384 sn ref &expr
385 sn refm &mut expr
386 sn some Some(expr)
387 "#]], 387 "#]],
388 ) 388 )
389 } 389 }
@@ -398,20 +398,20 @@ fn main() {
398} 398}
399"#, 399"#,
400 expect![[r#" 400 expect![[r#"
401 sn box Box::new(expr)
402 sn call function(expr)
403 sn dbg dbg!(expr)
404 sn dbgr dbg!(&expr)
405 sn if if expr {} 401 sn if if expr {}
406 sn let let 402 sn while while expr {}
407 sn letm let mut
408 sn match match expr {}
409 sn not !expr 403 sn not !expr
410 sn ok Ok(expr)
411 sn ref &expr 404 sn ref &expr
412 sn refm &mut expr 405 sn refm &mut expr
406 sn match match expr {}
407 sn box Box::new(expr)
408 sn ok Ok(expr)
413 sn some Some(expr) 409 sn some Some(expr)
414 sn while while expr {} 410 sn dbg dbg!(expr)
411 sn dbgr dbg!(&expr)
412 sn call function(expr)
413 sn let let
414 sn letm let mut
415 "#]], 415 "#]],
416 ); 416 );
417 } 417 }
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
index bc23bea3f..1300f00b2 100644
--- a/crates/completion/src/completions/qualified_path.rs
+++ b/crates/completion/src/completions/qualified_path.rs
@@ -199,22 +199,22 @@ use self::{foo::*, bar<|>};
199 check_builtin( 199 check_builtin(
200 r#"fn main() { let _: <|> = 92; }"#, 200 r#"fn main() { let _: <|> = 92; }"#,
201 expect![[r#" 201 expect![[r#"
202 bt u32
202 bt bool 203 bt bool
203 bt char 204 bt u8
205 bt isize
206 bt u16
207 bt u64
208 bt u128
204 bt f32 209 bt f32
205 bt f64
206 bt i128 210 bt i128
207 bt i16 211 bt i16
208 bt i32 212 bt str
209 bt i64 213 bt i64
214 bt char
215 bt f64
216 bt i32
210 bt i8 217 bt i8
211 bt isize
212 bt str
213 bt u128
214 bt u16
215 bt u32
216 bt u64
217 bt u8
218 bt usize 218 bt usize
219 "#]], 219 "#]],
220 ); 220 );
@@ -279,8 +279,8 @@ struct Spam;
279use crate::Sp<|> 279use crate::Sp<|>
280"#, 280"#,
281 expect![[r#" 281 expect![[r#"
282 st Spam
283 md foo 282 md foo
283 st Spam
284 "#]], 284 "#]],
285 ); 285 );
286 } 286 }
@@ -296,8 +296,8 @@ struct Spam;
296use crate::{Sp<|>}; 296use crate::{Sp<|>};
297"#, 297"#,
298 expect![[r#" 298 expect![[r#"
299 st Spam
300 md foo 299 md foo
300 st Spam
301 "#]], 301 "#]],
302 ); 302 );
303 } 303 }
@@ -330,8 +330,8 @@ enum E { Foo, Bar(i32) }
330fn foo() { let _ = E::<|> } 330fn foo() { let _ = E::<|> }
331"#, 331"#,
332 expect![[r#" 332 expect![[r#"
333 ev Bar(…) (i32)
334 ev Foo () 333 ev Foo ()
334 ev Bar(…) (i32)
335 "#]], 335 "#]],
336 ); 336 );
337 } 337 }
@@ -353,10 +353,10 @@ impl S {
353fn foo() { let _ = S::<|> } 353fn foo() { let _ = S::<|> }
354"#, 354"#,
355 expect![[r#" 355 expect![[r#"
356 ct C const C: i32 = 42;
357 ta T type T = i32;
358 fn a() fn a() 356 fn a() fn a()
359 me b(…) fn b(&self) 357 me b(…) fn b(&self)
358 ct C const C: i32 = 42;
359 ta T type T = i32;
360 "#]], 360 "#]],
361 ); 361 );
362 } 362 }
@@ -381,9 +381,9 @@ mod m {
381fn foo() { let _ = S::<|> } 381fn foo() { let _ = S::<|> }
382"#, 382"#,
383 expect![[r#" 383 expect![[r#"
384 fn public_method() pub(crate) fn public_method()
384 ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1; 385 ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1;
385 ta PublicType pub(crate) type PublicType = u32; 386 ta PublicType pub(crate) type PublicType = u32;
386 fn public_method() pub(crate) fn public_method()
387 "#]], 387 "#]],
388 ); 388 );
389 } 389 }
@@ -503,14 +503,14 @@ trait Sub: Super {
503fn foo<T: Sub>() { T::<|> } 503fn foo<T: Sub>() { T::<|> }
504"#, 504"#,
505 expect![[r#" 505 expect![[r#"
506 ct C2 const C2: ();
507 ct CONST const CONST: u8;
508 ta SubTy type SubTy; 506 ta SubTy type SubTy;
509 ta Ty type Ty; 507 ta Ty type Ty;
510 fn func() fn func() 508 ct C2 const C2: ();
511 me method(…) fn method(&self)
512 fn subfunc() fn subfunc() 509 fn subfunc() fn subfunc()
513 me submethod(…) fn submethod(&self) 510 me submethod(…) fn submethod(&self)
511 ct CONST const CONST: u8;
512 fn func() fn func()
513 me method(…) fn method(&self)
514 "#]], 514 "#]],
515 ); 515 );
516 } 516 }
@@ -543,12 +543,12 @@ impl<T> Sub for Wrap<T> {
543} 543}
544"#, 544"#,
545 expect![[r#" 545 expect![[r#"
546 ct C2 const C2: () = ();
547 ct CONST const CONST: u8 = 0;
548 ta SubTy type SubTy; 546 ta SubTy type SubTy;
549 ta Ty type Ty; 547 ta Ty type Ty;
548 ct CONST const CONST: u8 = 0;
550 fn func() fn func() 549 fn func() fn func()
551 me method(…) fn method(&self) 550 me method(…) fn method(&self)
551 ct C2 const C2: () = ();
552 fn subfunc() fn subfunc() 552 fn subfunc() fn subfunc()
553 me submethod(…) fn submethod(&self) 553 me submethod(…) fn submethod(&self)
554 "#]], 554 "#]],
@@ -567,8 +567,8 @@ impl T { fn bar() {} }
567fn main() { T::<|>; } 567fn main() { T::<|>; }
568"#, 568"#,
569 expect![[r#" 569 expect![[r#"
570 fn bar() fn bar()
571 fn foo() fn foo() 570 fn foo() fn foo()
571 fn bar() fn bar()
572 "#]], 572 "#]],
573 ); 573 );
574 } 574 }
@@ -583,9 +583,9 @@ macro_rules! foo { () => {} }
583fn main() { let _ = crate::<|> } 583fn main() { let _ = crate::<|> }
584 "#, 584 "#,
585 expect![[r##" 585 expect![[r##"
586 fn main() fn main()
586 ma foo!(…) #[macro_export] 587 ma foo!(…) #[macro_export]
587 macro_rules! foo 588 macro_rules! foo
588 fn main() fn main()
589 "##]], 589 "##]],
590 ); 590 );
591 } 591 }
@@ -603,8 +603,8 @@ mod a {
603} 603}
604"#, 604"#,
605 expect![[r#" 605 expect![[r#"
606 ct A
607 md b 606 md b
607 ct A
608 "#]], 608 "#]],
609 ); 609 );
610 } 610 }
@@ -628,8 +628,8 @@ mod p {
628"#, 628"#,
629 expect![[r#" 629 expect![[r#"
630 ct RIGHT_CONST 630 ct RIGHT_CONST
631 st RightType
632 fn right_fn() fn wrong_fn() 631 fn right_fn() fn wrong_fn()
632 st RightType
633 "#]], 633 "#]],
634 ); 634 );
635 635
@@ -675,8 +675,8 @@ fn main() { m!(self::f<|>); }
675fn foo() {} 675fn foo() {}
676"#, 676"#,
677 expect![[r#" 677 expect![[r#"
678 fn foo() fn foo()
679 fn main() fn main() 678 fn main() fn main()
679 fn foo() fn foo()
680 "#]], 680 "#]],
681 ); 681 );
682 } 682 }
@@ -747,8 +747,8 @@ fn main() {
747} 747}
748"#, 748"#,
749 expect![[r#" 749 expect![[r#"
750 fn foo(…) fn foo(a: i32, b: i32)
751 fn main() fn main() 750 fn main() fn main()
751 fn foo(…) fn foo(a: i32, b: i32)
752 "#]], 752 "#]],
753 ); 753 );
754 } 754 }
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs
index eaa44c97d..91bf4a8ad 100644
--- a/crates/completion/src/completions/record.rs
+++ b/crates/completion/src/completions/record.rs
@@ -94,9 +94,9 @@ fn process(f: S) {
94 check_snippet( 94 check_snippet(
95 test_code, 95 test_code,
96 expect![[r#" 96 expect![[r#"
97 fd ..Default::default()
98 sn pd 97 sn pd
99 sn ppd 98 sn ppd
99 fd ..Default::default()
100 "#]], 100 "#]],
101 ); 101 );
102 } 102 }
@@ -160,8 +160,8 @@ fn process(e: E) {
160} 160}
161"#, 161"#,
162 expect![[r#" 162 expect![[r#"
163 fd bar ()
164 fd foo u32 163 fd foo u32
164 fd bar ()
165 "#]], 165 "#]],
166 ); 166 );
167 } 167 }
diff --git a/crates/completion/src/completions/snippet.rs b/crates/completion/src/completions/snippet.rs
index 6f0c00078..842590130 100644
--- a/crates/completion/src/completions/snippet.rs
+++ b/crates/completion/src/completions/snippet.rs
@@ -105,9 +105,9 @@ mod tests {
105} 105}
106"#, 106"#,
107 expect![[r#" 107 expect![[r#"
108 sn macro_rules
109 sn tfn (Test function)
110 sn tmod (Test module) 108 sn tmod (Test module)
109 sn tfn (Test function)
110 sn macro_rules
111 "#]], 111 "#]],
112 ) 112 )
113 } 113 }
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs
index e2fe44aff..c4e0d0669 100644
--- a/crates/completion/src/completions/trait_impl.rs
+++ b/crates/completion/src/completions/trait_impl.rs
@@ -266,10 +266,10 @@ impl Test for T {
266} 266}
267"#, 267"#,
268 expect![[" 268 expect![["
269ta type TestType = \n\
269ct const TEST_CONST: u16 = \n\ 270ct const TEST_CONST: u16 = \n\
270fn fn test() 271fn fn test()
271ta type TestType = \n\ 272"]],
272 "]],
273 ); 273 );
274 } 274 }
275 275
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index b9315f6c0..099ffb4d4 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,7 +1,7 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use either::Either; 3use either::Either;
4use hir::{Adt, ModuleDef, ScopeDef, Type}; 4use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type};
5use ide_db::helpers::insert_use::ImportScope; 5use ide_db::helpers::insert_use::ImportScope;
6use ide_db::imports_locator; 6use ide_db::imports_locator;
7use syntax::AstNode; 7use syntax::AstNode;
@@ -126,7 +126,7 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
126 let anchor = ctx.name_ref_syntax.as_ref()?; 126 let anchor = ctx.name_ref_syntax.as_ref()?;
127 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; 127 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
128 128
129 let possible_imports = imports_locator::find_similar_imports( 129 let mut all_mod_paths = imports_locator::find_similar_imports(
130 &ctx.sema, 130 &ctx.sema,
131 ctx.krate?, 131 ctx.krate?,
132 Some(100), 132 Some(100),
@@ -144,33 +144,65 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
144 }) 144 })
145 }) 145 })
146 .filter(|(mod_path, _)| mod_path.len() > 1) 146 .filter(|(mod_path, _)| mod_path.len() > 1)
147 .filter_map(|(import_path, definition)| { 147 .collect::<Vec<_>>();
148
149 let user_input_lowercased = potential_import_name.to_lowercase();
150 all_mod_paths.sort_by_cached_key(|(mod_path, _)| {
151 compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased)
152 });
153
154 acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| {
148 render_resolution_with_import( 155 render_resolution_with_import(
149 RenderContext::new(ctx), 156 RenderContext::new(ctx),
150 ImportEdit { import_path, import_scope: import_scope.clone() }, 157 ImportEdit { import_path, import_scope: import_scope.clone() },
151 &definition, 158 &definition,
152 ) 159 )
153 }); 160 }));
154
155 acc.add_all(possible_imports);
156 Some(()) 161 Some(())
157} 162}
158 163
164fn compute_fuzzy_completion_order_key(
165 proposed_mod_path: &ModPath,
166 user_input_lowercased: &str,
167) -> usize {
168 mark::hit!(certain_fuzzy_order_test);
169 let proposed_import_name = match proposed_mod_path.segments.last() {
170 Some(name) => name.to_string().to_lowercase(),
171 None => return usize::MAX,
172 };
173 match proposed_import_name.match_indices(user_input_lowercased).next() {
174 Some((first_matching_index, _)) => first_matching_index,
175 None => usize::MAX,
176 }
177}
178
159#[cfg(test)] 179#[cfg(test)]
160mod tests { 180mod tests {
161 use expect_test::{expect, Expect}; 181 use expect_test::{expect, Expect};
162 use test_utils::mark; 182 use test_utils::mark;
163 183
164 use crate::{ 184 use crate::{
165 test_utils::{check_edit, check_edit_with_config, completion_list}, 185 test_utils::{check_edit, check_edit_with_config, completion_list_with_config},
166 CompletionConfig, CompletionKind, 186 CompletionConfig, CompletionKind,
167 }; 187 };
168 188
169 fn check(ra_fixture: &str, expect: Expect) { 189 fn check(ra_fixture: &str, expect: Expect) {
170 let actual = completion_list(ra_fixture, CompletionKind::Reference); 190 check_with_config(CompletionConfig::default(), ra_fixture, expect);
191 }
192
193 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
194 let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
171 expect.assert_eq(&actual) 195 expect.assert_eq(&actual)
172 } 196 }
173 197
198 fn fuzzy_completion_config() -> CompletionConfig {
199 let mut completion_config = CompletionConfig::default();
200 completion_config
201 .active_resolve_capabilities
202 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
203 completion_config
204 }
205
174 #[test] 206 #[test]
175 fn self_fulfilling_completion() { 207 fn self_fulfilling_completion() {
176 mark::check!(self_fulfilling_completion); 208 mark::check!(self_fulfilling_completion);
@@ -246,9 +278,9 @@ fn quux(x: i32) {
246} 278}
247"#, 279"#,
248 expect![[r#" 280 expect![[r#"
249 fn quux(…) fn quux(x: i32)
250 bn x i32
251 bn y i32 281 bn y i32
282 bn x i32
283 fn quux(…) fn quux(x: i32)
252 "#]], 284 "#]],
253 ); 285 );
254 } 286 }
@@ -268,8 +300,8 @@ fn quux() {
268} 300}
269"#, 301"#,
270 expect![[r#" 302 expect![[r#"
271 bn a
272 bn b i32 303 bn b i32
304 bn a
273 fn quux() fn quux() 305 fn quux() fn quux()
274 "#]], 306 "#]],
275 ); 307 );
@@ -284,8 +316,8 @@ fn quux() {
284} 316}
285"#, 317"#,
286 expect![[r#" 318 expect![[r#"
287 fn quux() fn quux()
288 bn x 319 bn x
320 fn quux() fn quux()
289 "#]], 321 "#]],
290 ); 322 );
291 } 323 }
@@ -326,9 +358,9 @@ fn main() {
326 check( 358 check(
327 r#"struct S<T> { x: <|>}"#, 359 r#"struct S<T> { x: <|>}"#,
328 expect![[r#" 360 expect![[r#"
329 st S<…>
330 tp Self 361 tp Self
331 tp T 362 tp T
363 st S<…>
332 "#]], 364 "#]],
333 ); 365 );
334 } 366 }
@@ -353,9 +385,9 @@ enum E {}
353fn quux() { <|> } 385fn quux() { <|> }
354"#, 386"#,
355 expect![[r#" 387 expect![[r#"
356 en E
357 st S 388 st S
358 fn quux() fn quux() 389 fn quux() fn quux()
390 en E
359 "#]], 391 "#]],
360 ); 392 );
361 } 393 }
@@ -407,8 +439,8 @@ mod m {
407} 439}
408"#, 440"#,
409 expect![[r#" 441 expect![[r#"
410 st Bar
411 fn quux() fn quux() 442 fn quux() fn quux()
443 st Bar
412 "#]], 444 "#]],
413 ); 445 );
414 } 446 }
@@ -453,8 +485,8 @@ fn foo() {
453 check( 485 check(
454 r#"impl S { fn foo(&self) { <|> } }"#, 486 r#"impl S { fn foo(&self) { <|> } }"#,
455 expect![[r#" 487 expect![[r#"
456 tp Self
457 bn self &{unknown} 488 bn self &{unknown}
489 tp Self
458 "#]], 490 "#]],
459 ); 491 );
460 } 492 }
@@ -473,9 +505,9 @@ use prelude::*;
473mod prelude { struct Option; } 505mod prelude { struct Option; }
474"#, 506"#,
475 expect![[r#" 507 expect![[r#"
476 st Option
477 fn foo() fn foo() 508 fn foo() fn foo()
478 md std 509 md std
510 st Option
479 "#]], 511 "#]],
480 ); 512 );
481 } 513 }
@@ -500,10 +532,10 @@ use prelude::*;
500mod prelude { struct String; } 532mod prelude { struct String; }
501"#, 533"#,
502 expect![[r#" 534 expect![[r#"
503 st String
504 md core
505 fn foo() fn foo() 535 fn foo() fn foo()
506 md std 536 md std
537 md core
538 st String
507 "#]], 539 "#]],
508 ); 540 );
509 } 541 }
@@ -529,13 +561,13 @@ mod m2 {
529fn main() { let v = <|> } 561fn main() { let v = <|> }
530"#, 562"#,
531 expect![[r##" 563 expect![[r##"
532 ma bar!(…) macro_rules! bar 564 md m1
533 ma baz!(…) #[macro_export] 565 ma baz!(…) #[macro_export]
534 macro_rules! baz 566 macro_rules! baz
535 ma foo!(…) macro_rules! foo
536 md m1
537 md m2
538 fn main() fn main() 567 fn main() fn main()
568 md m2
569 ma bar!(…) macro_rules! bar
570 ma foo!(…) macro_rules! foo
539 "##]], 571 "##]],
540 ); 572 );
541 } 573 }
@@ -548,8 +580,8 @@ macro_rules! foo { () => {} }
548fn foo() { <|> } 580fn foo() { <|> }
549"#, 581"#,
550 expect![[r#" 582 expect![[r#"
551 ma foo!(…) macro_rules! foo
552 fn foo() fn foo() 583 fn foo() fn foo()
584 ma foo!(…) macro_rules! foo
553 "#]], 585 "#]],
554 ); 586 );
555 } 587 }
@@ -562,8 +594,8 @@ macro_rules! foo { () => {} }
562fn main() { let x: <|> } 594fn main() { let x: <|> }
563"#, 595"#,
564 expect![[r#" 596 expect![[r#"
565 ma foo!(…) macro_rules! foo
566 fn main() fn main() 597 fn main() fn main()
598 ma foo!(…) macro_rules! foo
567 "#]], 599 "#]],
568 ); 600 );
569 } 601 }
@@ -576,8 +608,8 @@ macro_rules! foo { () => {} }
576fn main() { <|> } 608fn main() { <|> }
577"#, 609"#,
578 expect![[r#" 610 expect![[r#"
579 ma foo!(…) macro_rules! foo
580 fn main() fn main() 611 fn main() fn main()
612 ma foo!(…) macro_rules! foo
581 "#]], 613 "#]],
582 ); 614 );
583 } 615 }
@@ -609,10 +641,10 @@ fn quux(x: i32) {
609} 641}
610"#, 642"#,
611 expect![[r#" 643 expect![[r#"
612 ma m!(…) macro_rules! m
613 fn quux(…) fn quux(x: i32)
614 bn x i32
615 bn y i32 644 bn y i32
645 bn x i32
646 fn quux(…) fn quux(x: i32)
647 ma m!(…) macro_rules! m
616 "#]], 648 "#]],
617 ); 649 );
618 } 650 }
@@ -628,10 +660,10 @@ fn quux(x: i32) {
628} 660}
629", 661",
630 expect![[r#" 662 expect![[r#"
631 ma m!(…) macro_rules! m
632 fn quux(…) fn quux(x: i32)
633 bn x i32
634 bn y i32 663 bn y i32
664 bn x i32
665 fn quux(…) fn quux(x: i32)
666 ma m!(…) macro_rules! m
635 "#]], 667 "#]],
636 ); 668 );
637 } 669 }
@@ -647,10 +679,10 @@ fn quux(x: i32) {
647} 679}
648"#, 680"#,
649 expect![[r#" 681 expect![[r#"
650 ma m!(…) macro_rules! m
651 fn quux(…) fn quux(x: i32)
652 bn x i32
653 bn y i32 682 bn y i32
683 bn x i32
684 fn quux(…) fn quux(x: i32)
685 ma m!(…) macro_rules! m
654 "#]], 686 "#]],
655 ); 687 );
656 } 688 }
@@ -664,8 +696,8 @@ use spam::Quux;
664fn main() { <|> } 696fn main() { <|> }
665"#, 697"#,
666 expect![[r#" 698 expect![[r#"
667 ?? Quux
668 fn main() fn main() 699 fn main() fn main()
700 ?? Quux
669 "#]], 701 "#]],
670 ); 702 );
671 } 703 }
@@ -681,10 +713,10 @@ fn main() {
681} 713}
682"#, 714"#,
683 expect![[r#" 715 expect![[r#"
684 en Foo
685 ev Foo::Bar () 716 ev Foo::Bar ()
686 ev Foo::Baz () 717 ev Foo::Baz ()
687 ev Foo::Quux () 718 ev Foo::Quux ()
719 en Foo
688 "#]], 720 "#]],
689 ) 721 )
690 } 722 }
@@ -701,10 +733,10 @@ fn main() {
701} 733}
702"#, 734"#,
703 expect![[r#" 735 expect![[r#"
704 en Foo
705 ev Foo::Bar () 736 ev Foo::Bar ()
706 ev Foo::Baz () 737 ev Foo::Baz ()
707 ev Foo::Quux () 738 ev Foo::Quux ()
739 en Foo
708 "#]], 740 "#]],
709 ) 741 )
710 } 742 }
@@ -717,10 +749,10 @@ enum Foo { Bar, Baz, Quux }
717fn main() { let foo: Foo = Q<|> } 749fn main() { let foo: Foo = Q<|> }
718"#, 750"#,
719 expect![[r#" 751 expect![[r#"
720 en Foo
721 ev Foo::Bar () 752 ev Foo::Bar ()
722 ev Foo::Baz () 753 ev Foo::Baz ()
723 ev Foo::Quux () 754 ev Foo::Quux ()
755 en Foo
724 fn main() fn main() 756 fn main() fn main()
725 "#]], 757 "#]],
726 ) 758 )
@@ -734,9 +766,9 @@ mod m { pub enum E { V } }
734fn f() -> m::E { V<|> } 766fn f() -> m::E { V<|> }
735"#, 767"#,
736 expect![[r#" 768 expect![[r#"
737 fn f() fn f() -> m::E
738 md m
739 ev m::E::V () 769 ev m::E::V ()
770 md m
771 fn f() fn f() -> m::E
740 "#]], 772 "#]],
741 ) 773 )
742 } 774 }
@@ -763,22 +795,17 @@ struct MyStruct {}
763impl My<|> 795impl My<|>
764"#, 796"#,
765 expect![[r#" 797 expect![[r#"
766 st MyStruct
767 tt MyTrait
768 tp Self 798 tp Self
799 tt MyTrait
800 st MyStruct
769 "#]], 801 "#]],
770 ) 802 )
771 } 803 }
772 804
773 #[test] 805 #[test]
774 fn function_fuzzy_completion() { 806 fn function_fuzzy_completion() {
775 let mut completion_config = CompletionConfig::default();
776 completion_config
777 .active_resolve_capabilities
778 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
779
780 check_edit_with_config( 807 check_edit_with_config(
781 completion_config, 808 fuzzy_completion_config(),
782 "stdin", 809 "stdin",
783 r#" 810 r#"
784//- /lib.rs crate:dep 811//- /lib.rs crate:dep
@@ -803,13 +830,8 @@ fn main() {
803 830
804 #[test] 831 #[test]
805 fn macro_fuzzy_completion() { 832 fn macro_fuzzy_completion() {
806 let mut completion_config = CompletionConfig::default();
807 completion_config
808 .active_resolve_capabilities
809 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
810
811 check_edit_with_config( 833 check_edit_with_config(
812 completion_config, 834 fuzzy_completion_config(),
813 "macro_with_curlies!", 835 "macro_with_curlies!",
814 r#" 836 r#"
815//- /lib.rs crate:dep 837//- /lib.rs crate:dep
@@ -836,13 +858,8 @@ fn main() {
836 858
837 #[test] 859 #[test]
838 fn struct_fuzzy_completion() { 860 fn struct_fuzzy_completion() {
839 let mut completion_config = CompletionConfig::default();
840 completion_config
841 .active_resolve_capabilities
842 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
843
844 check_edit_with_config( 861 check_edit_with_config(
845 completion_config, 862 fuzzy_completion_config(),
846 "ThirdStruct", 863 "ThirdStruct",
847 r#" 864 r#"
848//- /lib.rs crate:dep 865//- /lib.rs crate:dep
@@ -868,4 +885,44 @@ fn main() {
868"#, 885"#,
869 ); 886 );
870 } 887 }
888
889 #[test]
890 fn fuzzy_completions_come_in_specific_order() {
891 mark::check!(certain_fuzzy_order_test);
892 check_with_config(
893 fuzzy_completion_config(),
894 r#"
895//- /lib.rs crate:dep
896pub struct FirstStruct;
897pub mod some_module {
898 // already imported, omitted
899 pub struct SecondStruct;
900 // does not contain all letters from the query, omitted
901 pub struct UnrelatedOne;
902 // contains all letters from the query, but not in sequence, displayed last
903 pub struct ThiiiiiirdStruct;
904 // contains all letters from the query, but not in the beginning, displayed second
905 pub struct AfterThirdStruct;
906 // contains all letters from the query in the begginning, displayed first
907 pub struct ThirdStruct;
908}
909
910//- /main.rs crate:main deps:dep
911use dep::{FirstStruct, some_module::SecondStruct};
912
913fn main() {
914 hir<|>
915}
916"#,
917 expect![[r#"
918 fn main() fn main()
919 st SecondStruct
920 st FirstStruct
921 md dep
922 st dep::some_module::ThirdStruct
923 st dep::some_module::AfterThirdStruct
924 st dep::some_module::ThiiiiiirdStruct
925 "#]],
926 );
927 }
871} 928}
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index b940388df..1092a4825 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -19,7 +19,7 @@ use crate::{
19 CompletionKind, CompletionScore, 19 CompletionKind, CompletionScore,
20}; 20};
21 21
22use crate::render::{enum_variant::render_enum_variant, function::render_fn, macro_::render_macro}; 22use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro};
23 23
24pub(crate) fn render_field<'a>( 24pub(crate) fn render_field<'a>(
25 ctx: RenderContext<'a>, 25 ctx: RenderContext<'a>,
@@ -159,9 +159,8 @@ impl<'a> Render<'a> {
159 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); 159 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func);
160 return Some(item); 160 return Some(item);
161 } 161 }
162 ScopeDef::ModuleDef(EnumVariant(var)) => { 162 ScopeDef::ModuleDef(Variant(var)) => {
163 let item = 163 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None);
164 render_enum_variant(self.ctx, import_to_add, Some(local_name), *var, None);
165 return Some(item); 164 return Some(item);
166 } 165 }
167 ScopeDef::MacroDef(mac) => { 166 ScopeDef::MacroDef(mac) => {
@@ -257,7 +256,7 @@ impl<'a> Render<'a> {
257 match resolution { 256 match resolution {
258 ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()), 257 ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()),
259 ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()), 258 ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()),
260 ScopeDef::ModuleDef(EnumVariant(it)) => it.docs(self.ctx.db()), 259 ScopeDef::ModuleDef(Variant(it)) => it.docs(self.ctx.db()),
261 ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()), 260 ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()),
262 ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()), 261 ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()),
263 ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()), 262 ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()),
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index 8e0fea6c0..7176fd9b3 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -9,35 +9,35 @@ use crate::{
9 render::{builder_ext::Params, RenderContext}, 9 render::{builder_ext::Params, RenderContext},
10}; 10};
11 11
12pub(crate) fn render_enum_variant<'a>( 12pub(crate) fn render_variant<'a>(
13 ctx: RenderContext<'a>, 13 ctx: RenderContext<'a>,
14 import_to_add: Option<ImportEdit>, 14 import_to_add: Option<ImportEdit>,
15 local_name: Option<String>, 15 local_name: Option<String>,
16 variant: hir::EnumVariant, 16 variant: hir::Variant,
17 path: Option<ModPath>, 17 path: Option<ModPath>,
18) -> CompletionItem { 18) -> CompletionItem {
19 let _p = profile::span("render_enum_variant"); 19 let _p = profile::span("render_enum_variant");
20 EnumVariantRender::new(ctx, local_name, variant, path).render(import_to_add) 20 EnumRender::new(ctx, local_name, variant, path).render(import_to_add)
21} 21}
22 22
23#[derive(Debug)] 23#[derive(Debug)]
24struct EnumVariantRender<'a> { 24struct EnumRender<'a> {
25 ctx: RenderContext<'a>, 25 ctx: RenderContext<'a>,
26 name: String, 26 name: String,
27 variant: hir::EnumVariant, 27 variant: hir::Variant,
28 path: Option<ModPath>, 28 path: Option<ModPath>,
29 qualified_name: String, 29 qualified_name: String,
30 short_qualified_name: String, 30 short_qualified_name: String,
31 variant_kind: StructKind, 31 variant_kind: StructKind,
32} 32}
33 33
34impl<'a> EnumVariantRender<'a> { 34impl<'a> EnumRender<'a> {
35 fn new( 35 fn new(
36 ctx: RenderContext<'a>, 36 ctx: RenderContext<'a>,
37 local_name: Option<String>, 37 local_name: Option<String>,
38 variant: hir::EnumVariant, 38 variant: hir::Variant,
39 path: Option<ModPath>, 39 path: Option<ModPath>,
40 ) -> EnumVariantRender<'a> { 40 ) -> EnumRender<'a> {
41 let name = local_name.unwrap_or_else(|| variant.name(ctx.db()).to_string()); 41 let name = local_name.unwrap_or_else(|| variant.name(ctx.db()).to_string());
42 let variant_kind = variant.kind(ctx.db()); 42 let variant_kind = variant.kind(ctx.db());
43 43
@@ -51,15 +51,7 @@ impl<'a> EnumVariantRender<'a> {
51 None => (name.to_string(), name.to_string()), 51 None => (name.to_string(), name.to_string()),
52 }; 52 };
53 53
54 EnumVariantRender { 54 EnumRender { ctx, name, variant, path, qualified_name, short_qualified_name, variant_kind }
55 ctx,
56 name,
57 variant,
58 path,
59 qualified_name,
60 short_qualified_name,
61 variant_kind,
62 }
63 } 55 }
64 56
65 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { 57 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index 6cfbd6c9b..dac79592f 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -41,6 +41,7 @@ impl<'a> MacroRender<'a> {
41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { 41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
42 // FIXME: Currently proc-macro do not have ast-node, 42 // FIXME: Currently proc-macro do not have ast-node,
43 // such that it does not have source 43 // such that it does not have source
44 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
44 if self.macro_.is_proc_macro() { 45 if self.macro_.is_proc_macro() {
45 return None; 46 return None;
46 } 47 }
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
index db896b2df..eb0c16f52 100644
--- a/crates/completion/src/test_utils.rs
+++ b/crates/completion/src/test_utils.rs
@@ -47,9 +47,8 @@ pub(crate) fn completion_list_with_config(
47 code: &str, 47 code: &str,
48 kind: CompletionKind, 48 kind: CompletionKind,
49) -> String { 49) -> String {
50 let mut kind_completions: Vec<CompletionItem> = 50 let kind_completions: Vec<CompletionItem> =
51 get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect(); 51 get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect();
52 kind_completions.sort_by_key(|c| c.label().to_owned());
53 let label_width = kind_completions 52 let label_width = kind_completions
54 .iter() 53 .iter()
55 .map(|it| monospace_width(it.label())) 54 .map(|it| monospace_width(it.label()))
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 1f2ee2580..d32ce37ed 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -10,8 +10,8 @@ use hir_ty::db::HirDatabase;
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
13 Adt, Const, Enum, EnumVariant, Field, Function, MacroDef, Module, ModuleDef, Static, Struct, 13 Adt, Const, Enum, Field, Function, MacroDef, Module, ModuleDef, Static, Struct, Trait,
14 Trait, TypeAlias, Union, 14 TypeAlias, Union, Variant,
15}; 15};
16 16
17pub trait HasAttrs { 17pub trait HasAttrs {
@@ -53,7 +53,7 @@ macro_rules! impl_has_attrs {
53 53
54impl_has_attrs![ 54impl_has_attrs![
55 (Field, FieldId), 55 (Field, FieldId),
56 (EnumVariant, EnumVariantId), 56 (Variant, EnumVariantId),
57 (Static, StaticId), 57 (Static, StaticId),
58 (Const, ConstId), 58 (Const, ConstId),
59 (Trait, TraitId), 59 (Trait, TraitId),
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index afe229c32..73ca6ba9f 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -161,7 +161,7 @@ pub enum ModuleDef {
161 Function(Function), 161 Function(Function),
162 Adt(Adt), 162 Adt(Adt),
163 // Can't be directly declared, but can be imported. 163 // Can't be directly declared, but can be imported.
164 EnumVariant(EnumVariant), 164 Variant(Variant),
165 Const(Const), 165 Const(Const),
166 Static(Static), 166 Static(Static),
167 Trait(Trait), 167 Trait(Trait),
@@ -172,7 +172,7 @@ impl_from!(
172 Module, 172 Module,
173 Function, 173 Function,
174 Adt(Struct, Enum, Union), 174 Adt(Struct, Enum, Union),
175 EnumVariant, 175 Variant,
176 Const, 176 Const,
177 Static, 177 Static,
178 Trait, 178 Trait,
@@ -186,7 +186,7 @@ impl From<VariantDef> for ModuleDef {
186 match var { 186 match var {
187 VariantDef::Struct(t) => Adt::from(t).into(), 187 VariantDef::Struct(t) => Adt::from(t).into(),
188 VariantDef::Union(t) => Adt::from(t).into(), 188 VariantDef::Union(t) => Adt::from(t).into(),
189 VariantDef::EnumVariant(t) => t.into(), 189 VariantDef::Variant(t) => t.into(),
190 } 190 }
191 } 191 }
192} 192}
@@ -197,7 +197,7 @@ impl ModuleDef {
197 ModuleDef::Module(it) => it.parent(db), 197 ModuleDef::Module(it) => it.parent(db),
198 ModuleDef::Function(it) => Some(it.module(db)), 198 ModuleDef::Function(it) => Some(it.module(db)),
199 ModuleDef::Adt(it) => Some(it.module(db)), 199 ModuleDef::Adt(it) => Some(it.module(db)),
200 ModuleDef::EnumVariant(it) => Some(it.module(db)), 200 ModuleDef::Variant(it) => Some(it.module(db)),
201 ModuleDef::Const(it) => Some(it.module(db)), 201 ModuleDef::Const(it) => Some(it.module(db)),
202 ModuleDef::Static(it) => Some(it.module(db)), 202 ModuleDef::Static(it) => Some(it.module(db)),
203 ModuleDef::Trait(it) => Some(it.module(db)), 203 ModuleDef::Trait(it) => Some(it.module(db)),
@@ -221,7 +221,7 @@ impl ModuleDef {
221 ModuleDef::Module(it) => it.parent(db)?, 221 ModuleDef::Module(it) => it.parent(db)?,
222 ModuleDef::Function(it) => return Some(it.visibility(db)), 222 ModuleDef::Function(it) => return Some(it.visibility(db)),
223 ModuleDef::Adt(it) => it.module(db), 223 ModuleDef::Adt(it) => it.module(db),
224 ModuleDef::EnumVariant(it) => { 224 ModuleDef::Variant(it) => {
225 let parent = it.parent_enum(db); 225 let parent = it.parent_enum(db);
226 let module = it.module(db); 226 let module = it.module(db);
227 return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent))); 227 return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)));
@@ -241,7 +241,7 @@ impl ModuleDef {
241 ModuleDef::Adt(it) => Some(it.name(db)), 241 ModuleDef::Adt(it) => Some(it.name(db)),
242 ModuleDef::Trait(it) => Some(it.name(db)), 242 ModuleDef::Trait(it) => Some(it.name(db)),
243 ModuleDef::Function(it) => Some(it.name(db)), 243 ModuleDef::Function(it) => Some(it.name(db)),
244 ModuleDef::EnumVariant(it) => Some(it.name(db)), 244 ModuleDef::Variant(it) => Some(it.name(db)),
245 ModuleDef::TypeAlias(it) => Some(it.name(db)), 245 ModuleDef::TypeAlias(it) => Some(it.name(db)),
246 ModuleDef::Module(it) => it.name(db), 246 ModuleDef::Module(it) => it.name(db),
247 ModuleDef::Const(it) => it.name(db), 247 ModuleDef::Const(it) => it.name(db),
@@ -455,7 +455,7 @@ impl Field {
455 let generic_def_id: GenericDefId = match self.parent { 455 let generic_def_id: GenericDefId = match self.parent {
456 VariantDef::Struct(it) => it.id.into(), 456 VariantDef::Struct(it) => it.id.into(),
457 VariantDef::Union(it) => it.id.into(), 457 VariantDef::Union(it) => it.id.into(),
458 VariantDef::EnumVariant(it) => it.parent.id.into(), 458 VariantDef::Variant(it) => it.parent.id.into(),
459 }; 459 };
460 let substs = Substs::type_params(db, generic_def_id); 460 let substs = Substs::type_params(db, generic_def_id);
461 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 461 let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
@@ -566,12 +566,8 @@ impl Enum {
566 db.enum_data(self.id).name.clone() 566 db.enum_data(self.id).name.clone()
567 } 567 }
568 568
569 pub fn variants(self, db: &dyn HirDatabase) -> Vec<EnumVariant> { 569 pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
570 db.enum_data(self.id) 570 db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
571 .variants
572 .iter()
573 .map(|(id, _)| EnumVariant { parent: self, id })
574 .collect()
575 } 571 }
576 572
577 pub fn ty(self, db: &dyn HirDatabase) -> Type { 573 pub fn ty(self, db: &dyn HirDatabase) -> Type {
@@ -580,12 +576,12 @@ impl Enum {
580} 576}
581 577
582#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 578#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
583pub struct EnumVariant { 579pub struct Variant {
584 pub(crate) parent: Enum, 580 pub(crate) parent: Enum,
585 pub(crate) id: LocalEnumVariantId, 581 pub(crate) id: LocalEnumVariantId,
586} 582}
587 583
588impl EnumVariant { 584impl Variant {
589 pub fn module(self, db: &dyn HirDatabase) -> Module { 585 pub fn module(self, db: &dyn HirDatabase) -> Module {
590 self.parent.module(db) 586 self.parent.module(db)
591 } 587 }
@@ -662,16 +658,16 @@ impl Adt {
662pub enum VariantDef { 658pub enum VariantDef {
663 Struct(Struct), 659 Struct(Struct),
664 Union(Union), 660 Union(Union),
665 EnumVariant(EnumVariant), 661 Variant(Variant),
666} 662}
667impl_from!(Struct, Union, EnumVariant for VariantDef); 663impl_from!(Struct, Union, Variant for VariantDef);
668 664
669impl VariantDef { 665impl VariantDef {
670 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { 666 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
671 match self { 667 match self {
672 VariantDef::Struct(it) => it.fields(db), 668 VariantDef::Struct(it) => it.fields(db),
673 VariantDef::Union(it) => it.fields(db), 669 VariantDef::Union(it) => it.fields(db),
674 VariantDef::EnumVariant(it) => it.fields(db), 670 VariantDef::Variant(it) => it.fields(db),
675 } 671 }
676 } 672 }
677 673
@@ -679,7 +675,7 @@ impl VariantDef {
679 match self { 675 match self {
680 VariantDef::Struct(it) => it.module(db), 676 VariantDef::Struct(it) => it.module(db),
681 VariantDef::Union(it) => it.module(db), 677 VariantDef::Union(it) => it.module(db),
682 VariantDef::EnumVariant(it) => it.module(db), 678 VariantDef::Variant(it) => it.module(db),
683 } 679 }
684 } 680 }
685 681
@@ -687,7 +683,7 @@ impl VariantDef {
687 match self { 683 match self {
688 VariantDef::Struct(s) => s.name(db), 684 VariantDef::Struct(s) => s.name(db),
689 VariantDef::Union(u) => u.name(db), 685 VariantDef::Union(u) => u.name(db),
690 VariantDef::EnumVariant(e) => e.name(db), 686 VariantDef::Variant(e) => e.name(db),
691 } 687 }
692 } 688 }
693 689
@@ -695,7 +691,7 @@ impl VariantDef {
695 match self { 691 match self {
696 VariantDef::Struct(it) => it.variant_data(db), 692 VariantDef::Struct(it) => it.variant_data(db),
697 VariantDef::Union(it) => it.variant_data(db), 693 VariantDef::Union(it) => it.variant_data(db),
698 VariantDef::EnumVariant(it) => it.variant_data(db), 694 VariantDef::Variant(it) => it.variant_data(db),
699 } 695 }
700 } 696 }
701} 697}
@@ -983,6 +979,12 @@ impl MacroDef {
983 979
984 /// XXX: this parses the file 980 /// XXX: this parses the file
985 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 981 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
982 // FIXME: Currently proc-macro do not have ast-node,
983 // such that it does not have source
984 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
985 if self.is_proc_macro() {
986 return None;
987 }
986 self.source(db).value.name().map(|it| it.as_name()) 988 self.source(db).value.name().map(|it| it.as_name())
987 } 989 }
988 990
@@ -1089,7 +1091,7 @@ pub enum GenericDef {
1089 Impl(Impl), 1091 Impl(Impl),
1090 // enum variants cannot have generics themselves, but their parent enums 1092 // enum variants cannot have generics themselves, but their parent enums
1091 // can, and this makes some code easier to write 1093 // can, and this makes some code easier to write
1092 EnumVariant(EnumVariant), 1094 Variant(Variant),
1093 // consts can have type parameters from their parents (i.e. associated consts of traits) 1095 // consts can have type parameters from their parents (i.e. associated consts of traits)
1094 Const(Const), 1096 Const(Const),
1095} 1097}
@@ -1099,7 +1101,7 @@ impl_from!(
1099 Trait, 1101 Trait,
1100 TypeAlias, 1102 TypeAlias,
1101 Impl, 1103 Impl,
1102 EnumVariant, 1104 Variant,
1103 Const 1105 Const
1104 for GenericDef 1106 for GenericDef
1105); 1107);
@@ -1283,14 +1285,12 @@ impl Impl {
1283 impls.for_trait(trait_.id).map(Self::from).collect() 1285 impls.for_trait(trait_.id).map(Self::from).collect()
1284 } 1286 }
1285 1287
1288 // FIXME: the return type is wrong. This should be a hir version of
1289 // `TraitRef` (ie, resolved `TypeRef`).
1286 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1290 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1287 db.impl_data(self.id).target_trait.clone() 1291 db.impl_data(self.id).target_trait.clone()
1288 } 1292 }
1289 1293
1290 pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef {
1291 db.impl_data(self.id).target_type.clone()
1292 }
1293
1294 pub fn target_ty(self, db: &dyn HirDatabase) -> Type { 1294 pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
1295 let impl_data = db.impl_data(self.id); 1295 let impl_data = db.impl_data(self.id);
1296 let resolver = self.id.resolver(db.upcast()); 1296 let resolver = self.id.resolver(db.upcast());
@@ -1324,6 +1324,7 @@ impl Impl {
1324 let item = src.file_id.is_builtin_derive(db.upcast())?; 1324 let item = src.file_id.is_builtin_derive(db.upcast())?;
1325 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); 1325 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
1326 1326
1327 // FIXME: handle `cfg_attr`
1327 let attr = item 1328 let attr = item
1328 .value 1329 .value
1329 .attrs() 1330 .attrs()
@@ -1841,7 +1842,7 @@ pub struct Callable {
1841pub enum CallableKind { 1842pub enum CallableKind {
1842 Function(Function), 1843 Function(Function),
1843 TupleStruct(Struct), 1844 TupleStruct(Struct),
1844 TupleEnumVariant(EnumVariant), 1845 TupleEnumVariant(Variant),
1845 Closure, 1846 Closure,
1846} 1847}
1847 1848
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 8d0f84508..8e0c571b8 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -9,8 +9,7 @@ use hir_def::{
9}; 9};
10 10
11use crate::{ 11use crate::{
12 Adt, AssocItem, DefWithBody, EnumVariant, Field, GenericDef, Local, MacroDef, ModuleDef, 12 Adt, AssocItem, DefWithBody, Field, GenericDef, Local, MacroDef, ModuleDef, Variant, VariantDef,
13 VariantDef,
14}; 13};
15 14
16macro_rules! from_id { 15macro_rules! from_id {
@@ -65,14 +64,14 @@ impl From<Adt> for AdtId {
65 } 64 }
66} 65}
67 66
68impl From<EnumVariantId> for EnumVariant { 67impl From<EnumVariantId> for Variant {
69 fn from(id: EnumVariantId) -> Self { 68 fn from(id: EnumVariantId) -> Self {
70 EnumVariant { parent: id.parent.into(), id: id.local_id } 69 Variant { parent: id.parent.into(), id: id.local_id }
71 } 70 }
72} 71}
73 72
74impl From<EnumVariant> for EnumVariantId { 73impl From<Variant> for EnumVariantId {
75 fn from(def: EnumVariant) -> Self { 74 fn from(def: Variant) -> Self {
76 EnumVariantId { parent: def.parent.id, local_id: def.id } 75 EnumVariantId { parent: def.parent.id, local_id: def.id }
77 } 76 }
78} 77}
@@ -83,7 +82,7 @@ impl From<ModuleDefId> for ModuleDef {
83 ModuleDefId::ModuleId(it) => ModuleDef::Module(it.into()), 82 ModuleDefId::ModuleId(it) => ModuleDef::Module(it.into()),
84 ModuleDefId::FunctionId(it) => ModuleDef::Function(it.into()), 83 ModuleDefId::FunctionId(it) => ModuleDef::Function(it.into()),
85 ModuleDefId::AdtId(it) => ModuleDef::Adt(it.into()), 84 ModuleDefId::AdtId(it) => ModuleDef::Adt(it.into()),
86 ModuleDefId::EnumVariantId(it) => ModuleDef::EnumVariant(it.into()), 85 ModuleDefId::EnumVariantId(it) => ModuleDef::Variant(it.into()),
87 ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()), 86 ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()),
88 ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()), 87 ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()),
89 ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()), 88 ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()),
@@ -99,7 +98,7 @@ impl From<ModuleDef> for ModuleDefId {
99 ModuleDef::Module(it) => ModuleDefId::ModuleId(it.into()), 98 ModuleDef::Module(it) => ModuleDefId::ModuleId(it.into()),
100 ModuleDef::Function(it) => ModuleDefId::FunctionId(it.into()), 99 ModuleDef::Function(it) => ModuleDefId::FunctionId(it.into()),
101 ModuleDef::Adt(it) => ModuleDefId::AdtId(it.into()), 100 ModuleDef::Adt(it) => ModuleDefId::AdtId(it.into()),
102 ModuleDef::EnumVariant(it) => ModuleDefId::EnumVariantId(it.into()), 101 ModuleDef::Variant(it) => ModuleDefId::EnumVariantId(it.into()),
103 ModuleDef::Const(it) => ModuleDefId::ConstId(it.into()), 102 ModuleDef::Const(it) => ModuleDefId::ConstId(it.into()),
104 ModuleDef::Static(it) => ModuleDefId::StaticId(it.into()), 103 ModuleDef::Static(it) => ModuleDefId::StaticId(it.into()),
105 ModuleDef::Trait(it) => ModuleDefId::TraitId(it.into()), 104 ModuleDef::Trait(it) => ModuleDefId::TraitId(it.into()),
@@ -147,7 +146,7 @@ impl From<GenericDef> for GenericDefId {
147 GenericDef::Trait(it) => GenericDefId::TraitId(it.id), 146 GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
148 GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), 147 GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
149 GenericDef::Impl(it) => GenericDefId::ImplId(it.id), 148 GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
150 GenericDef::EnumVariant(it) => { 149 GenericDef::Variant(it) => {
151 GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id }) 150 GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
152 } 151 }
153 GenericDef::Const(it) => GenericDefId::ConstId(it.id), 152 GenericDef::Const(it) => GenericDefId::ConstId(it.id),
@@ -164,7 +163,7 @@ impl From<GenericDefId> for GenericDef {
164 GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), 163 GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
165 GenericDefId::ImplId(it) => GenericDef::Impl(it.into()), 164 GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
166 GenericDefId::EnumVariantId(it) => { 165 GenericDefId::EnumVariantId(it) => {
167 GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id }) 166 GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id })
168 } 167 }
169 GenericDefId::ConstId(it) => GenericDef::Const(it.into()), 168 GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
170 } 169 }
@@ -185,7 +184,7 @@ impl From<VariantId> for VariantDef {
185 fn from(def: VariantId) -> Self { 184 fn from(def: VariantId) -> Self {
186 match def { 185 match def {
187 VariantId::StructId(it) => VariantDef::Struct(it.into()), 186 VariantId::StructId(it) => VariantDef::Struct(it.into()),
188 VariantId::EnumVariantId(it) => VariantDef::EnumVariant(it.into()), 187 VariantId::EnumVariantId(it) => VariantDef::Variant(it.into()),
189 VariantId::UnionId(it) => VariantDef::Union(it.into()), 188 VariantId::UnionId(it) => VariantDef::Union(it.into()),
190 } 189 }
191 } 190 }
@@ -195,7 +194,7 @@ impl From<VariantDef> for VariantId {
195 fn from(def: VariantDef) -> Self { 194 fn from(def: VariantDef) -> Self {
196 match def { 195 match def {
197 VariantDef::Struct(it) => VariantId::StructId(it.id), 196 VariantDef::Struct(it) => VariantId::StructId(it.id),
198 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()), 197 VariantDef::Variant(it) => VariantId::EnumVariantId(it.into()),
199 VariantDef::Union(it) => VariantId::UnionId(it.id), 198 VariantDef::Union(it) => VariantId::UnionId(it.id),
200 } 199 }
201 } 200 }
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index c5b81b252..0dc07c33e 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -10,8 +10,8 @@ use hir_expand::InFile;
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, Impl, LifetimeParam, 13 db::HirDatabase, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef,
14 MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, 14 Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
15}; 15};
16 16
17pub trait HasSource { 17pub trait HasSource {
@@ -73,7 +73,7 @@ impl HasSource for Enum {
73 self.id.lookup(db.upcast()).source(db.upcast()) 73 self.id.lookup(db.upcast()).source(db.upcast())
74 } 74 }
75} 75}
76impl HasSource for EnumVariant { 76impl HasSource for Variant {
77 type Ast = ast::Variant; 77 type Ast = ast::Variant;
78 fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> { 78 fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> {
79 self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()) 79 self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 3f4f8d8e4..bdd270c58 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -34,9 +34,9 @@ pub use crate::{
34 attrs::{HasAttrs, Namespace}, 34 attrs::{HasAttrs, Namespace},
35 code_model::{ 35 code_model::{
36 Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, 36 Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
37 Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function, 37 Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef,
38 GenericDef, HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef, 38 HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, Static,
39 ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, 39 Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
40 }, 40 },
41 has_source::HasSource, 41 has_source::HasSource,
42 semantics::{PathResolution, Semantics, SemanticsScope}, 42 semantics::{PathResolution, Semantics, SemanticsScope},
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 83ec91f58..25ebf73d8 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -51,7 +51,7 @@ impl PathResolution {
51 Some(TypeNs::BuiltinType(*builtin)) 51 Some(TypeNs::BuiltinType(*builtin))
52 } 52 }
53 PathResolution::Def(ModuleDef::Const(_)) 53 PathResolution::Def(ModuleDef::Const(_))
54 | PathResolution::Def(ModuleDef::EnumVariant(_)) 54 | PathResolution::Def(ModuleDef::Variant(_))
55 | PathResolution::Def(ModuleDef::Function(_)) 55 | PathResolution::Def(ModuleDef::Function(_))
56 | PathResolution::Def(ModuleDef::Module(_)) 56 | PathResolution::Def(ModuleDef::Module(_))
57 | PathResolution::Def(ModuleDef::Static(_)) 57 | PathResolution::Def(ModuleDef::Static(_))
@@ -715,7 +715,7 @@ to_def_impls![
715 (crate::Function, ast::Fn, fn_to_def), 715 (crate::Function, ast::Fn, fn_to_def),
716 (crate::Field, ast::RecordField, record_field_to_def), 716 (crate::Field, ast::RecordField, record_field_to_def),
717 (crate::Field, ast::TupleField, tuple_field_to_def), 717 (crate::Field, ast::TupleField, tuple_field_to_def),
718 (crate::EnumVariant, ast::Variant, enum_variant_to_def), 718 (crate::Variant, ast::Variant, enum_variant_to_def),
719 (crate::TypeParam, ast::TypeParam, type_param_to_def), 719 (crate::TypeParam, ast::TypeParam, type_param_to_def),
720 (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def), 720 (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
721 (crate::MacroDef, ast::MacroRules, macro_rules_to_def), 721 (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index bf0c959fe..bddc49c05 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -28,8 +28,8 @@ use syntax::{
28}; 28};
29 29
30use crate::{ 30use crate::{
31 db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Field, Function, Local, 31 db::HirDatabase, semantics::PathResolution, Adt, Const, Field, Function, Local, MacroDef,
32 MacroDef, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, 32 ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Variant,
33}; 33};
34use base_db::CrateId; 34use base_db::CrateId;
35 35
@@ -230,7 +230,7 @@ impl SourceAnalyzer {
230 if let Some(VariantId::EnumVariantId(variant)) = 230 if let Some(VariantId::EnumVariantId(variant)) =
231 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 231 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
232 { 232 {
233 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); 233 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
234 } 234 }
235 } 235 }
236 236
@@ -242,7 +242,7 @@ impl SourceAnalyzer {
242 if let Some(VariantId::EnumVariantId(variant)) = 242 if let Some(VariantId::EnumVariantId(variant)) =
243 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 243 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
244 { 244 {
245 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); 245 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
246 } 246 }
247 } 247 }
248 248
@@ -251,7 +251,7 @@ impl SourceAnalyzer {
251 if let Some(VariantId::EnumVariantId(variant)) = 251 if let Some(VariantId::EnumVariantId(variant)) =
252 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 252 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
253 { 253 {
254 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); 254 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
255 } 255 }
256 } 256 }
257 257
@@ -260,7 +260,7 @@ impl SourceAnalyzer {
260 if let Some(VariantId::EnumVariantId(variant)) = 260 if let Some(VariantId::EnumVariantId(variant)) =
261 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 261 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
262 { 262 {
263 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); 263 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
264 } 264 }
265 } 265 }
266 266
@@ -459,7 +459,7 @@ pub(crate) fn resolve_hir_path(
459 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 459 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
460 PathResolution::Def(Adt::from(it).into()) 460 PathResolution::Def(Adt::from(it).into())
461 } 461 }
462 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), 462 TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
463 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), 463 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
464 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), 464 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
465 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 465 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
@@ -477,7 +477,7 @@ pub(crate) fn resolve_hir_path(
477 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), 477 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
478 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), 478 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
479 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), 479 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
480 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), 480 ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
481 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), 481 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
482 }; 482 };
483 Some(res) 483 Some(res)
@@ -526,7 +526,7 @@ fn resolve_hir_path_qualifier(
526 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 526 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
527 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), 527 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
528 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()), 528 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()),
529 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), 529 TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
530 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), 530 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
531 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), 531 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
532 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 532 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index eafa3abb6..236d6f1b7 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -3,6 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use arena::{map::ArenaMap, Arena}; 5use arena::{map::ArenaMap, Arena};
6use base_db::CrateId;
6use either::Either; 7use either::Either;
7use hir_expand::{ 8use hir_expand::{
8 name::{AsName, Name}, 9 name::{AsName, Name},
@@ -66,8 +67,13 @@ pub enum ReprKind {
66 Other, 67 Other,
67} 68}
68 69
69fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> { 70fn repr_from_value(
70 item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt) 71 db: &dyn DefDatabase,
72 krate: CrateId,
73 item_tree: &ItemTree,
74 of: AttrOwner,
75) -> Option<ReprKind> {
76 item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
71} 77}
72 78
73fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { 79fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
@@ -86,12 +92,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
86impl StructData { 92impl StructData {
87 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { 93 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
88 let loc = id.lookup(db); 94 let loc = id.lookup(db);
95 let krate = loc.container.module(db).krate;
89 let item_tree = db.item_tree(loc.id.file_id); 96 let item_tree = db.item_tree(loc.id.file_id);
90 let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); 97 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
91 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 98 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
92 99
93 let strukt = &item_tree[loc.id.value]; 100 let strukt = &item_tree[loc.id.value];
94 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None); 101 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
95 Arc::new(StructData { 102 Arc::new(StructData {
96 name: strukt.name.clone(), 103 name: strukt.name.clone(),
97 variant_data: Arc::new(variant_data), 104 variant_data: Arc::new(variant_data),
@@ -100,12 +107,13 @@ impl StructData {
100 } 107 }
101 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 108 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
102 let loc = id.lookup(db); 109 let loc = id.lookup(db);
110 let krate = loc.container.module(db).krate;
103 let item_tree = db.item_tree(loc.id.file_id); 111 let item_tree = db.item_tree(loc.id.file_id);
104 let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); 112 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
105 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 113 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
106 114
107 let union = &item_tree[loc.id.value]; 115 let union = &item_tree[loc.id.value];
108 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None); 116 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
109 117
110 Arc::new(StructData { 118 Arc::new(StructData {
111 name: union.name.clone(), 119 name: union.name.clone(),
@@ -118,16 +126,23 @@ impl StructData {
118impl EnumData { 126impl EnumData {
119 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { 127 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
120 let loc = e.lookup(db); 128 let loc = e.lookup(db);
129 let krate = loc.container.module(db).krate;
121 let item_tree = db.item_tree(loc.id.file_id); 130 let item_tree = db.item_tree(loc.id.file_id);
122 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 131 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
123 132
124 let enum_ = &item_tree[loc.id.value]; 133 let enum_ = &item_tree[loc.id.value];
125 let mut variants = Arena::new(); 134 let mut variants = Arena::new();
126 for var_id in enum_.variants.clone() { 135 for var_id in enum_.variants.clone() {
127 if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) { 136 if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) {
128 let var = &item_tree[var_id]; 137 let var = &item_tree[var_id];
129 let var_data = 138 let var_data = lower_fields(
130 lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility)); 139 db,
140 krate,
141 &item_tree,
142 &cfg_options,
143 &var.fields,
144 Some(enum_.visibility),
145 );
131 146
132 variants.alloc(EnumVariantData { 147 variants.alloc(EnumVariantData {
133 name: var.name.clone(), 148 name: var.name.clone(),
@@ -170,7 +185,7 @@ fn lower_enum(
170 .variant_list() 185 .variant_list()
171 .into_iter() 186 .into_iter()
172 .flat_map(|it| it.variants()) 187 .flat_map(|it| it.variants())
173 .filter(|var| expander.is_cfg_enabled(var)); 188 .filter(|var| expander.is_cfg_enabled(db, var));
174 for var in variants { 189 for var in variants {
175 trace.alloc( 190 trace.alloc(
176 || var.clone(), 191 || var.clone(),
@@ -262,7 +277,7 @@ fn lower_struct(
262 match &ast.value { 277 match &ast.value {
263 ast::StructKind::Tuple(fl) => { 278 ast::StructKind::Tuple(fl) => {
264 for (i, fd) in fl.fields().enumerate() { 279 for (i, fd) in fl.fields().enumerate() {
265 if !expander.is_cfg_enabled(&fd) { 280 if !expander.is_cfg_enabled(db, &fd) {
266 continue; 281 continue;
267 } 282 }
268 283
@@ -279,7 +294,7 @@ fn lower_struct(
279 } 294 }
280 ast::StructKind::Record(fl) => { 295 ast::StructKind::Record(fl) => {
281 for fd in fl.fields() { 296 for fd in fl.fields() {
282 if !expander.is_cfg_enabled(&fd) { 297 if !expander.is_cfg_enabled(db, &fd) {
283 continue; 298 continue;
284 } 299 }
285 300
@@ -299,6 +314,8 @@ fn lower_struct(
299} 314}
300 315
301fn lower_fields( 316fn lower_fields(
317 db: &dyn DefDatabase,
318 krate: CrateId,
302 item_tree: &ItemTree, 319 item_tree: &ItemTree,
303 cfg_options: &CfgOptions, 320 cfg_options: &CfgOptions,
304 fields: &Fields, 321 fields: &Fields,
@@ -308,7 +325,7 @@ fn lower_fields(
308 Fields::Record(flds) => { 325 Fields::Record(flds) => {
309 let mut arena = Arena::new(); 326 let mut arena = Arena::new();
310 for field_id in flds.clone() { 327 for field_id in flds.clone() {
311 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { 328 if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
312 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); 329 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
313 } 330 }
314 } 331 }
@@ -317,7 +334,7 @@ fn lower_fields(
317 Fields::Tuple(flds) => { 334 Fields::Tuple(flds) => {
318 let mut arena = Arena::new(); 335 let mut arena = Arena::new();
319 for field_id in flds.clone() { 336 for field_id in flds.clone() {
320 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { 337 if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
321 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); 338 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
322 } 339 }
323 } 340 }
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index c64b78445..042e119b1 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -2,22 +2,24 @@
2 2
3use std::{ops, sync::Arc}; 3use std::{ops, sync::Arc};
4 4
5use base_db::CrateId;
5use cfg::{CfgExpr, CfgOptions}; 6use cfg::{CfgExpr, CfgOptions};
6use either::Either; 7use either::Either;
7use hir_expand::{hygiene::Hygiene, AstId, InFile}; 8use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
8use itertools::Itertools; 9use itertools::Itertools;
9use mbe::ast_to_token_tree; 10use mbe::ast_to_token_tree;
10use syntax::{ 11use syntax::{
11 ast::{self, AstNode, AttrsOwner}, 12 ast::{self, AstNode, AttrsOwner},
12 match_ast, AstToken, SmolStr, SyntaxNode, 13 match_ast, AstToken, SmolStr, SyntaxNode,
13}; 14};
15use test_utils::mark;
14use tt::Subtree; 16use tt::Subtree;
15 17
16use crate::{ 18use crate::{
17 db::DefDatabase, 19 db::DefDatabase,
18 item_tree::{ItemTreeId, ItemTreeNode}, 20 item_tree::{ItemTreeId, ItemTreeNode},
19 nameres::ModuleSource, 21 nameres::ModuleSource,
20 path::ModPath, 22 path::{ModPath, PathKind},
21 src::HasChildSource, 23 src::HasChildSource,
22 AdtId, AttrDefId, Lookup, 24 AdtId, AttrDefId, Lookup,
23}; 25};
@@ -38,12 +40,16 @@ impl From<Documentation> for String {
38 } 40 }
39} 41}
40 42
43/// Syntactical attributes, without filtering of `cfg_attr`s.
41#[derive(Default, Debug, Clone, PartialEq, Eq)] 44#[derive(Default, Debug, Clone, PartialEq, Eq)]
42pub struct Attrs { 45pub(crate) struct RawAttrs {
43 entries: Option<Arc<[Attr]>>, 46 entries: Option<Arc<[Attr]>>,
44} 47}
45 48
46impl ops::Deref for Attrs { 49#[derive(Default, Debug, Clone, PartialEq, Eq)]
50pub struct Attrs(RawAttrs);
51
52impl ops::Deref for RawAttrs {
47 type Target = [Attr]; 53 type Target = [Attr];
48 54
49 fn deref(&self) -> &[Attr] { 55 fn deref(&self) -> &[Attr] {
@@ -54,19 +60,147 @@ impl ops::Deref for Attrs {
54 } 60 }
55} 61}
56 62
63impl ops::Deref for Attrs {
64 type Target = [Attr];
65
66 fn deref(&self) -> &[Attr] {
67 match &self.0.entries {
68 Some(it) => &*it,
69 None => &[],
70 }
71 }
72}
73
74impl RawAttrs {
75 pub(crate) const EMPTY: Self = Self { entries: None };
76
77 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self {
78 let attrs: Vec<_> = collect_attrs(owner).collect();
79 let entries = if attrs.is_empty() {
80 // Avoid heap allocation
81 None
82 } else {
83 Some(
84 attrs
85 .into_iter()
86 .enumerate()
87 .flat_map(|(i, attr)| match attr {
88 Either::Left(attr) => Attr::from_src(attr, hygiene).map(|attr| (i, attr)),
89 Either::Right(comment) => comment.doc_comment().map(|doc| {
90 (
91 i,
92 Attr {
93 index: 0,
94 input: Some(AttrInput::Literal(SmolStr::new(doc))),
95 path: ModPath::from(hir_expand::name!(doc)),
96 },
97 )
98 }),
99 })
100 .map(|(i, attr)| Attr { index: i as u32, ..attr })
101 .collect(),
102 )
103 };
104 Self { entries }
105 }
106
107 fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self {
108 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
109 Self::new(owner.value, &hygiene)
110 }
111
112 pub(crate) fn merge(&self, other: Self) -> Self {
113 match (&self.entries, &other.entries) {
114 (None, None) => Self::EMPTY,
115 (Some(entries), None) | (None, Some(entries)) => {
116 Self { entries: Some(entries.clone()) }
117 }
118 (Some(a), Some(b)) => {
119 Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
120 }
121 }
122 }
123
124 /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
125 pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
126 let has_cfg_attrs = self.iter().any(|attr| {
127 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
128 });
129 if !has_cfg_attrs {
130 return Attrs(self);
131 }
132
133 let crate_graph = db.crate_graph();
134 let new_attrs = self
135 .iter()
136 .filter_map(|attr| {
137 let attr = attr.clone();
138 let is_cfg_attr =
139 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
140 if !is_cfg_attr {
141 return Some(attr);
142 }
143
144 let subtree = match &attr.input {
145 Some(AttrInput::TokenTree(it)) => it,
146 _ => return Some(attr),
147 };
148
149 // Input subtree is: `(cfg, attr)`
150 // Split it up into a `cfg` and an `attr` subtree.
151 // FIXME: There should be a common API for this.
152 let mut saw_comma = false;
153 let (mut cfg, attr): (Vec<_>, Vec<_>) =
154 subtree.clone().token_trees.into_iter().partition(|tree| {
155 if saw_comma {
156 return false;
157 }
158
159 match tree {
160 tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
161 saw_comma = true;
162 }
163 _ => {}
164 }
165
166 true
167 });
168 cfg.pop(); // `,` ends up in here
169
170 let attr = Subtree { delimiter: None, token_trees: attr };
171 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg };
172 let cfg = CfgExpr::parse(&cfg);
173
174 let cfg_options = &crate_graph[krate].cfg_options;
175 if cfg_options.check(&cfg) == Some(false) {
176 None
177 } else {
178 mark::hit!(cfg_attr_active);
179
180 let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?;
181 let hygiene = Hygiene::new_unhygienic(); // FIXME
182 Attr::from_src(attr, &hygiene)
183 }
184 })
185 .collect();
186
187 Attrs(RawAttrs { entries: Some(new_attrs) })
188 }
189}
190
57impl Attrs { 191impl Attrs {
58 pub const EMPTY: Attrs = Attrs { entries: None }; 192 pub const EMPTY: Self = Self(RawAttrs::EMPTY);
59 193
60 pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { 194 pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
61 match def { 195 let raw_attrs = match def {
62 AttrDefId::ModuleId(module) => { 196 AttrDefId::ModuleId(module) => {
63 let def_map = db.crate_def_map(module.krate); 197 let def_map = db.crate_def_map(module.krate);
64 let mod_data = &def_map[module.local_id]; 198 let mod_data = &def_map[module.local_id];
65 match mod_data.declaration_source(db) { 199 match mod_data.declaration_source(db) {
66 Some(it) => { 200 Some(it) => {
67 Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) 201 RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
68 } 202 }
69 None => Attrs::from_attrs_owner( 203 None => RawAttrs::from_attrs_owner(
70 db, 204 db,
71 mod_data.definition_source(db).as_ref().map(|src| match src { 205 mod_data.definition_source(db).as_ref().map(|src| match src {
72 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, 206 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
@@ -78,14 +212,14 @@ impl Attrs {
78 AttrDefId::FieldId(it) => { 212 AttrDefId::FieldId(it) => {
79 let src = it.parent.child_source(db); 213 let src = it.parent.child_source(db);
80 match &src.value[it.local_id] { 214 match &src.value[it.local_id] {
81 Either::Left(_tuple) => Attrs::default(), 215 Either::Left(_tuple) => RawAttrs::default(),
82 Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)), 216 Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)),
83 } 217 }
84 } 218 }
85 AttrDefId::EnumVariantId(var_id) => { 219 AttrDefId::EnumVariantId(var_id) => {
86 let src = var_id.parent.child_source(db); 220 let src = var_id.parent.child_source(db);
87 let src = src.as_ref().map(|it| &it[var_id.local_id]); 221 let src = src.as_ref().map(|it| &it[var_id.local_id]);
88 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) 222 RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
89 } 223 }
90 AttrDefId::AdtId(it) => match it { 224 AttrDefId::AdtId(it) => match it {
91 AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), 225 AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
@@ -101,55 +235,9 @@ impl Attrs {
101 AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), 235 AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
102 AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), 236 AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
103 AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), 237 AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
104 }
105 }
106
107 pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
108 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
109 Attrs::new(owner.value, &hygiene)
110 }
111
112 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
113 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
114 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
115
116 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
117 let attrs = outer_attrs
118 .chain(inner_attrs.into_iter().flatten())
119 .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene)));
120
121 let outer_docs =
122 ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
123 let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| {
124 (
125 docs_text.syntax().text_range().start(),
126 docs_text.doc_comment().map(|doc| Attr {
127 input: Some(AttrInput::Literal(SmolStr::new(doc))),
128 path: ModPath::from(hir_expand::name!(doc)),
129 }),
130 )
131 });
132 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
133 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect();
134 let entries = if attrs.is_empty() {
135 // Avoid heap allocation
136 None
137 } else {
138 Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect())
139 }; 238 };
140 Attrs { entries }
141 }
142 239
143 pub fn merge(&self, other: Attrs) -> Attrs { 240 raw_attrs.filter(db, def.krate(db))
144 match (&self.entries, &other.entries) {
145 (None, None) => Attrs { entries: None },
146 (Some(entries), None) | (None, Some(entries)) => {
147 Attrs { entries: Some(entries.clone()) }
148 }
149 (Some(a), Some(b)) => {
150 Attrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
151 }
152 }
153 } 241 }
154 242
155 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { 243 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
@@ -157,7 +245,6 @@ impl Attrs {
157 } 245 }
158 246
159 pub fn cfg(&self) -> Option<CfgExpr> { 247 pub fn cfg(&self) -> Option<CfgExpr> {
160 // FIXME: handle cfg_attr :-)
161 let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse).collect::<Vec<_>>(); 248 let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse).collect::<Vec<_>>();
162 match cfgs.len() { 249 match cfgs.len() {
163 0 => None, 250 0 => None,
@@ -228,6 +315,7 @@ fn inner_attributes(
228 315
229#[derive(Debug, Clone, PartialEq, Eq)] 316#[derive(Debug, Clone, PartialEq, Eq)]
230pub struct Attr { 317pub struct Attr {
318 index: u32,
231 pub(crate) path: ModPath, 319 pub(crate) path: ModPath,
232 pub(crate) input: Option<AttrInput>, 320 pub(crate) input: Option<AttrInput>,
233} 321}
@@ -254,7 +342,59 @@ impl Attr {
254 } else { 342 } else {
255 None 343 None
256 }; 344 };
257 Some(Attr { path, input }) 345 Some(Attr { index: 0, path, input })
346 }
347
348 /// Maps this lowered `Attr` back to its original syntax node.
349 ///
350 /// `owner` must be the original owner of the attribute.
351 ///
352 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
353 /// the attribute represented by `Attr`.
354 pub fn to_src(&self, owner: &dyn AttrsOwner) -> Either<ast::Attr, ast::Comment> {
355 collect_attrs(owner).nth(self.index as usize).unwrap_or_else(|| {
356 panic!("cannot find `Attr` at index {} in {}", self.index, owner.syntax())
357 })
358 }
359
360 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
361 /// to derive macros.
362 ///
363 /// Returns `None` when the attribute is not a well-formed `#[derive]` attribute.
364 pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
365 if self.path.as_ident() != Some(&hir_expand::name![derive]) {
366 return None;
367 }
368
369 match &self.input {
370 Some(AttrInput::TokenTree(args)) => {
371 let mut counter = 0;
372 let paths = args
373 .token_trees
374 .iter()
375 .group_by(move |tt| {
376 match tt {
377 tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
378 counter += 1;
379 }
380 _ => {}
381 }
382 counter
383 })
384 .into_iter()
385 .map(|(_, tts)| {
386 let segments = tts.filter_map(|tt| match tt {
387 tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
388 _ => None,
389 });
390 ModPath::from_segments(PathKind::Plain, segments)
391 })
392 .collect::<Vec<_>>();
393
394 Some(paths.into_iter())
395 }
396 _ => None,
397 }
258 } 398 }
259} 399}
260 400
@@ -283,7 +423,7 @@ impl<'a> AttrQuery<'a> {
283 self.attrs().next().is_some() 423 self.attrs().next().is_some()
284 } 424 }
285 425
286 fn attrs(self) -> impl Iterator<Item = &'a Attr> { 426 pub(crate) fn attrs(self) -> impl Iterator<Item = &'a Attr> {
287 let key = self.key; 427 let key = self.key;
288 self.attrs 428 self.attrs
289 .iter() 429 .iter()
@@ -291,16 +431,36 @@ impl<'a> AttrQuery<'a> {
291 } 431 }
292} 432}
293 433
294fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> Attrs 434fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> RawAttrs
295where 435where
296 N: ast::AttrsOwner, 436 N: ast::AttrsOwner,
297{ 437{
298 let src = InFile::new(src.file_id, src.to_node(db.upcast())); 438 let src = InFile::new(src.file_id, src.to_node(db.upcast()));
299 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) 439 RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
300} 440}
301 441
302fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> Attrs { 442fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs {
303 let tree = db.item_tree(id.file_id); 443 let tree = db.item_tree(id.file_id);
304 let mod_item = N::id_to_mod_item(id.value); 444 let mod_item = N::id_to_mod_item(id.value);
305 tree.attrs(mod_item.into()).clone() 445 tree.raw_attrs(mod_item.into()).clone()
446}
447
448fn collect_attrs(owner: &dyn AttrsOwner) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> {
449 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
450 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
451
452 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
453 let attrs = outer_attrs
454 .chain(inner_attrs.into_iter().flatten())
455 .map(|attr| (attr.syntax().text_range().start(), Either::Left(attr)));
456
457 let outer_docs =
458 ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
459 let docs = outer_docs
460 .chain(inner_docs.into_iter().flatten())
461 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
462 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
463 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect();
464
465 attrs.into_iter().map(|(_, attr)| attr)
306} 466}
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index c5d6f5fb0..998b82601 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -24,7 +24,7 @@ use test_utils::mark;
24pub(crate) use lower::LowerCtx; 24pub(crate) use lower::LowerCtx;
25 25
26use crate::{ 26use crate::{
27 attr::Attrs, 27 attr::{Attrs, RawAttrs},
28 db::DefDatabase, 28 db::DefDatabase,
29 expr::{Expr, ExprId, Pat, PatId}, 29 expr::{Expr, ExprId, Pat, PatId},
30 item_scope::BuiltinShadowMode, 30 item_scope::BuiltinShadowMode,
@@ -40,6 +40,7 @@ use crate::{
40pub(crate) struct CfgExpander { 40pub(crate) struct CfgExpander {
41 cfg_options: CfgOptions, 41 cfg_options: CfgOptions,
42 hygiene: Hygiene, 42 hygiene: Hygiene,
43 krate: CrateId,
43} 44}
44 45
45pub(crate) struct Expander { 46pub(crate) struct Expander {
@@ -65,15 +66,15 @@ impl CfgExpander {
65 ) -> CfgExpander { 66 ) -> CfgExpander {
66 let hygiene = Hygiene::new(db.upcast(), current_file_id); 67 let hygiene = Hygiene::new(db.upcast(), current_file_id);
67 let cfg_options = db.crate_graph()[krate].cfg_options.clone(); 68 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
68 CfgExpander { cfg_options, hygiene } 69 CfgExpander { cfg_options, hygiene, krate }
69 } 70 }
70 71
71 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 72 pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
72 Attrs::new(owner, &self.hygiene) 73 RawAttrs::new(owner, &self.hygiene).filter(db, self.krate)
73 } 74 }
74 75
75 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { 76 pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool {
76 let attrs = self.parse_attrs(owner); 77 let attrs = self.parse_attrs(db, owner);
77 attrs.is_cfg_enabled(&self.cfg_options) 78 attrs.is_cfg_enabled(&self.cfg_options)
78 } 79 }
79} 80}
@@ -189,8 +190,8 @@ impl Expander {
189 InFile { file_id: self.current_file_id, value } 190 InFile { file_id: self.current_file_id, value }
190 } 191 }
191 192
192 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 193 pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
193 self.cfg_expander.parse_attrs(owner) 194 self.cfg_expander.parse_attrs(db, owner)
194 } 195 }
195 196
196 pub(crate) fn cfg_options(&self) -> &CfgOptions { 197 pub(crate) fn cfg_options(&self) -> &CfgOptions {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 3b3d74987..0f404be1b 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -963,7 +963,7 @@ impl ExprCollector<'_> {
963 /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when 963 /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
964 /// not. 964 /// not.
965 fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> { 965 fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> {
966 match self.expander.parse_attrs(owner).cfg() { 966 match self.expander.parse_attrs(self.db, owner).cfg() {
967 Some(cfg) => { 967 Some(cfg) => {
968 if self.expander.cfg_options().check(&cfg) != Some(false) { 968 if self.expander.cfg_options().check(&cfg) != Some(false) {
969 return Some(()); 969 return Some(());
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index dd3a906af..e7b7724f7 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -35,6 +35,7 @@ pub struct FunctionData {
35impl FunctionData { 35impl FunctionData {
36 pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { 36 pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
37 let loc = func.lookup(db); 37 let loc = func.lookup(db);
38 let krate = loc.container.module(db).krate;
38 let item_tree = db.item_tree(loc.id.file_id); 39 let item_tree = db.item_tree(loc.id.file_id);
39 let func = &item_tree[loc.id.value]; 40 let func = &item_tree[loc.id.value];
40 41
@@ -42,7 +43,7 @@ impl FunctionData {
42 name: func.name.clone(), 43 name: func.name.clone(),
43 params: func.params.to_vec(), 44 params: func.params.to_vec(),
44 ret_type: func.ret_type.clone(), 45 ret_type: func.ret_type.clone(),
45 attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), 46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(),
46 has_self_param: func.has_self_param, 47 has_self_param: func.has_self_param,
47 has_body: func.has_body, 48 has_body: func.has_body,
48 is_unsafe: func.is_unsafe, 49 is_unsafe: func.is_unsafe,
@@ -233,7 +234,7 @@ fn collect_items(
233 match item { 234 match item {
234 AssocItem::Function(id) => { 235 AssocItem::Function(id) => {
235 let item = &item_tree[id]; 236 let item = &item_tree[id];
236 let attrs = item_tree.attrs(ModItem::from(id).into()); 237 let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into());
237 if !attrs.is_cfg_enabled(&cfg_options) { 238 if !attrs.is_cfg_enabled(&cfg_options) {
238 continue; 239 continue;
239 } 240 }
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index b8e09e3af..100dbf5d6 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -12,7 +12,8 @@ use std::{
12}; 12};
13 13
14use arena::{Arena, Idx, RawId}; 14use arena::{Arena, Idx, RawId};
15use ast::{AstNode, AttrsOwner, NameOwner, StructKind}; 15use ast::{AstNode, NameOwner, StructKind};
16use base_db::CrateId;
16use either::Either; 17use either::Either;
17use hir_expand::{ 18use hir_expand::{
18 ast_id_map::FileAstId, 19 ast_id_map::FileAstId,
@@ -26,7 +27,7 @@ use syntax::{ast, match_ast};
26use test_utils::mark; 27use test_utils::mark;
27 28
28use crate::{ 29use crate::{
29 attr::Attrs, 30 attr::{Attrs, RawAttrs},
30 db::DefDatabase, 31 db::DefDatabase,
31 generics::GenericParams, 32 generics::GenericParams,
32 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, 33 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
@@ -67,7 +68,7 @@ impl GenericParamsId {
67#[derive(Debug, Eq, PartialEq)] 68#[derive(Debug, Eq, PartialEq)]
68pub struct ItemTree { 69pub struct ItemTree {
69 top_level: SmallVec<[ModItem; 1]>, 70 top_level: SmallVec<[ModItem; 1]>,
70 attrs: FxHashMap<AttrOwner, Attrs>, 71 attrs: FxHashMap<AttrOwner, RawAttrs>,
71 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, 72 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
72 73
73 data: Option<Box<ItemTreeData>>, 74 data: Option<Box<ItemTreeData>>,
@@ -88,7 +89,7 @@ impl ItemTree {
88 let mut item_tree = match_ast! { 89 let mut item_tree = match_ast! {
89 match syntax { 90 match syntax {
90 ast::SourceFile(file) => { 91 ast::SourceFile(file) => {
91 top_attrs = Some(Attrs::new(&file, &hygiene)); 92 top_attrs = Some(RawAttrs::new(&file, &hygiene));
92 ctx.lower_module_items(&file) 93 ctx.lower_module_items(&file)
93 }, 94 },
94 ast::MacroItems(items) => { 95 ast::MacroItems(items) => {
@@ -180,12 +181,16 @@ impl ItemTree {
180 } 181 }
181 182
182 /// Returns the inner attributes of the source file. 183 /// Returns the inner attributes of the source file.
183 pub fn top_level_attrs(&self) -> &Attrs { 184 pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
184 self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) 185 self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate)
185 } 186 }
186 187
187 pub fn attrs(&self, of: AttrOwner) -> &Attrs { 188 pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
188 self.attrs.get(&of).unwrap_or(&Attrs::EMPTY) 189 self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
190 }
191
192 pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
193 self.raw_attrs(of).clone().filter(db, krate)
189 } 194 }
190 195
191 /// Returns the lowered inner items that `ast` corresponds to. 196 /// Returns the lowered inner items that `ast` corresponds to.
@@ -490,7 +495,6 @@ pub struct Import {
490 pub alias: Option<ImportAlias>, 495 pub alias: Option<ImportAlias>,
491 pub visibility: RawVisibilityId, 496 pub visibility: RawVisibilityId,
492 pub is_glob: bool, 497 pub is_glob: bool,
493 pub is_prelude: bool,
494 /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many 498 /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
495 /// `Import`s can map to the same `use` item. 499 /// `Import`s can map to the same `use` item.
496 pub ast_id: FileAstId<ast::Use>, 500 pub ast_id: FileAstId<ast::Use>,
@@ -506,8 +510,6 @@ pub struct ExternCrate {
506 pub name: Name, 510 pub name: Name,
507 pub alias: Option<ImportAlias>, 511 pub alias: Option<ImportAlias>,
508 pub visibility: RawVisibilityId, 512 pub visibility: RawVisibilityId,
509 /// Whether this is a `#[macro_use] extern crate ...`.
510 pub is_macro_use: bool,
511 pub ast_id: FileAstId<ast::ExternCrate>, 513 pub ast_id: FileAstId<ast::ExternCrate>,
512} 514}
513 515
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 7de385ee8..3b206ef85 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -10,7 +10,6 @@ use syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 attr::Attrs,
14 generics::{GenericParams, TypeParamData, TypeParamProvenance}, 13 generics::{GenericParams, TypeParamData, TypeParamProvenance},
15 type_ref::LifetimeRef, 14 type_ref::LifetimeRef,
16}; 15};
@@ -105,7 +104,7 @@ impl Ctx {
105 | ast::Item::MacroDef(_) => {} 104 | ast::Item::MacroDef(_) => {}
106 }; 105 };
107 106
108 let attrs = Attrs::new(item, &self.hygiene); 107 let attrs = RawAttrs::new(item, &self.hygiene);
109 let items = match item { 108 let items = match item {
110 ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into), 109 ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
111 ast::Item::Union(ast) => self.lower_union(ast).map(Into::into), 110 ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
@@ -138,7 +137,7 @@ impl Ctx {
138 items 137 items
139 } 138 }
140 139
141 fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) { 140 fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) {
142 match self.tree.attrs.entry(item) { 141 match self.tree.attrs.entry(item) {
143 Entry::Occupied(mut entry) => { 142 Entry::Occupied(mut entry) => {
144 *entry.get_mut() = entry.get().merge(attrs); 143 *entry.get_mut() = entry.get().merge(attrs);
@@ -205,7 +204,7 @@ impl Ctx {
205 for field in fields.fields() { 204 for field in fields.fields() {
206 if let Some(data) = self.lower_record_field(&field) { 205 if let Some(data) = self.lower_record_field(&field) {
207 let idx = self.data().fields.alloc(data); 206 let idx = self.data().fields.alloc(data);
208 self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); 207 self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
209 } 208 }
210 } 209 }
211 let end = self.next_field_idx(); 210 let end = self.next_field_idx();
@@ -225,7 +224,7 @@ impl Ctx {
225 for (i, field) in fields.fields().enumerate() { 224 for (i, field) in fields.fields().enumerate() {
226 let data = self.lower_tuple_field(i, &field); 225 let data = self.lower_tuple_field(i, &field);
227 let idx = self.data().fields.alloc(data); 226 let idx = self.data().fields.alloc(data);
228 self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); 227 self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
229 } 228 }
230 let end = self.next_field_idx(); 229 let end = self.next_field_idx();
231 IdRange::new(start..end) 230 IdRange::new(start..end)
@@ -270,7 +269,7 @@ impl Ctx {
270 for variant in variants.variants() { 269 for variant in variants.variants() {
271 if let Some(data) = self.lower_variant(&variant) { 270 if let Some(data) = self.lower_variant(&variant) {
272 let idx = self.data().variants.alloc(data); 271 let idx = self.data().variants.alloc(data);
273 self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene)); 272 self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene));
274 } 273 }
275 } 274 }
276 let end = self.next_variant_idx(); 275 let end = self.next_variant_idx();
@@ -438,7 +437,7 @@ impl Ctx {
438 self.with_inherited_visibility(visibility, |this| { 437 self.with_inherited_visibility(visibility, |this| {
439 list.assoc_items() 438 list.assoc_items()
440 .filter_map(|item| { 439 .filter_map(|item| {
441 let attrs = Attrs::new(&item, &this.hygiene); 440 let attrs = RawAttrs::new(&item, &this.hygiene);
442 this.collect_inner_items(item.syntax()); 441 this.collect_inner_items(item.syntax());
443 this.lower_assoc_item(&item).map(|item| { 442 this.lower_assoc_item(&item).map(|item| {
444 this.add_attrs(ModItem::from(item).into(), attrs); 443 this.add_attrs(ModItem::from(item).into(), attrs);
@@ -475,7 +474,7 @@ impl Ctx {
475 .filter_map(|item| { 474 .filter_map(|item| {
476 self.collect_inner_items(item.syntax()); 475 self.collect_inner_items(item.syntax());
477 let assoc = self.lower_assoc_item(&item)?; 476 let assoc = self.lower_assoc_item(&item)?;
478 let attrs = Attrs::new(&item, &self.hygiene); 477 let attrs = RawAttrs::new(&item, &self.hygiene);
479 self.add_attrs(ModItem::from(assoc).into(), attrs); 478 self.add_attrs(ModItem::from(assoc).into(), attrs);
480 Some(assoc) 479 Some(assoc)
481 }) 480 })
@@ -486,8 +485,6 @@ impl Ctx {
486 } 485 }
487 486
488 fn lower_use(&mut self, use_item: &ast::Use) -> Vec<FileItemTreeId<Import>> { 487 fn lower_use(&mut self, use_item: &ast::Use) -> Vec<FileItemTreeId<Import>> {
489 // FIXME: cfg_attr
490 let is_prelude = use_item.has_atom_attr("prelude_import");
491 let visibility = self.lower_visibility(use_item); 488 let visibility = self.lower_visibility(use_item);
492 let ast_id = self.source_ast_id_map.ast_id(use_item); 489 let ast_id = self.source_ast_id_map.ast_id(use_item);
493 490
@@ -503,7 +500,6 @@ impl Ctx {
503 alias, 500 alias,
504 visibility, 501 visibility,
505 is_glob, 502 is_glob,
506 is_prelude,
507 ast_id, 503 ast_id,
508 index: imports.len(), 504 index: imports.len(),
509 }))); 505 })));
@@ -523,10 +519,8 @@ impl Ctx {
523 }); 519 });
524 let visibility = self.lower_visibility(extern_crate); 520 let visibility = self.lower_visibility(extern_crate);
525 let ast_id = self.source_ast_id_map.ast_id(extern_crate); 521 let ast_id = self.source_ast_id_map.ast_id(extern_crate);
526 // FIXME: cfg_attr
527 let is_macro_use = extern_crate.has_atom_attr("macro_use");
528 522
529 let res = ExternCrate { name, alias, visibility, is_macro_use, ast_id }; 523 let res = ExternCrate { name, alias, visibility, ast_id };
530 Some(id(self.data().extern_crates.alloc(res))) 524 Some(id(self.data().extern_crates.alloc(res)))
531 } 525 }
532 526
@@ -560,7 +554,7 @@ impl Ctx {
560 list.extern_items() 554 list.extern_items()
561 .filter_map(|item| { 555 .filter_map(|item| {
562 self.collect_inner_items(item.syntax()); 556 self.collect_inner_items(item.syntax());
563 let attrs = Attrs::new(&item, &self.hygiene); 557 let attrs = RawAttrs::new(&item, &self.hygiene);
564 let id: ModItem = match item { 558 let id: ModItem = match item {
565 ast::ExternItem::Fn(ast) => { 559 ast::ExternItem::Fn(ast) => {
566 let func_id = self.lower_function(&ast)?; 560 let func_id = self.lower_function(&ast)?;
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 7e2199a9c..ba09a9126 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -425,6 +425,16 @@ impl HasModule for AdtId {
425 } 425 }
426} 426}
427 427
428impl HasModule for VariantId {
429 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
430 match self {
431 VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db),
432 VariantId::StructId(it) => it.lookup(db).container.module(db),
433 VariantId::UnionId(it) => it.lookup(db).container.module(db),
434 }
435 }
436}
437
428impl HasModule for DefWithBodyId { 438impl HasModule for DefWithBodyId {
429 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { 439 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
430 match self { 440 match self {
@@ -465,6 +475,26 @@ impl HasModule for StaticLoc {
465 } 475 }
466} 476}
467 477
478impl AttrDefId {
479 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
480 match self {
481 AttrDefId::ModuleId(it) => it.krate,
482 AttrDefId::FieldId(it) => it.parent.module(db).krate,
483 AttrDefId::AdtId(it) => it.module(db).krate,
484 AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
485 AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate,
486 AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
487 AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
488 AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate,
489 AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
490 AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate,
491 // FIXME: `MacroDefId` should store the defining module, then this can implement
492 // `HasModule`
493 AttrDefId::MacroDefId(it) => it.krate,
494 }
495 }
496}
497
468/// A helper trait for converting to MacroCallId 498/// A helper trait for converting to MacroCallId
469pub trait AsMacroCall { 499pub trait AsMacroCall {
470 fn as_call_id( 500 fn as_call_id(
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 1936348fb..a636ec77d 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -136,23 +136,35 @@ struct Import {
136} 136}
137 137
138impl Import { 138impl Import {
139 fn from_use(tree: &ItemTree, id: ItemTreeId<item_tree::Import>) -> Self { 139 fn from_use(
140 db: &dyn DefDatabase,
141 krate: CrateId,
142 tree: &ItemTree,
143 id: ItemTreeId<item_tree::Import>,
144 ) -> Self {
140 let it = &tree[id.value]; 145 let it = &tree[id.value];
146 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
141 let visibility = &tree[it.visibility]; 147 let visibility = &tree[it.visibility];
142 Self { 148 Self {
143 path: it.path.clone(), 149 path: it.path.clone(),
144 alias: it.alias.clone(), 150 alias: it.alias.clone(),
145 visibility: visibility.clone(), 151 visibility: visibility.clone(),
146 is_glob: it.is_glob, 152 is_glob: it.is_glob,
147 is_prelude: it.is_prelude, 153 is_prelude: attrs.by_key("prelude_import").exists(),
148 is_extern_crate: false, 154 is_extern_crate: false,
149 is_macro_use: false, 155 is_macro_use: false,
150 source: ImportSource::Import(id), 156 source: ImportSource::Import(id),
151 } 157 }
152 } 158 }
153 159
154 fn from_extern_crate(tree: &ItemTree, id: ItemTreeId<item_tree::ExternCrate>) -> Self { 160 fn from_extern_crate(
161 db: &dyn DefDatabase,
162 krate: CrateId,
163 tree: &ItemTree,
164 id: ItemTreeId<item_tree::ExternCrate>,
165 ) -> Self {
155 let it = &tree[id.value]; 166 let it = &tree[id.value];
167 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
156 let visibility = &tree[it.visibility]; 168 let visibility = &tree[it.visibility];
157 Self { 169 Self {
158 path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), 170 path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
@@ -161,7 +173,7 @@ impl Import {
161 is_glob: false, 173 is_glob: false,
162 is_prelude: false, 174 is_prelude: false,
163 is_extern_crate: true, 175 is_extern_crate: true,
164 is_macro_use: it.is_macro_use, 176 is_macro_use: attrs.by_key("macro_use").exists(),
165 source: ImportSource::ExternCrate(id), 177 source: ImportSource::ExternCrate(id),
166 } 178 }
167 } 179 }
@@ -221,17 +233,20 @@ impl DefCollector<'_> {
221 let item_tree = self.db.item_tree(file_id.into()); 233 let item_tree = self.db.item_tree(file_id.into());
222 let module_id = self.def_map.root; 234 let module_id = self.def_map.root;
223 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; 235 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
224 let mut root_collector = ModCollector { 236 if item_tree
225 def_collector: &mut *self, 237 .top_level_attrs(self.db, self.def_map.krate)
226 macro_depth: 0, 238 .cfg()
227 module_id, 239 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
228 file_id: file_id.into(),
229 item_tree: &item_tree,
230 mod_dir: ModDir::root(),
231 };
232 if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg))
233 { 240 {
234 root_collector.collect(item_tree.top_level_items()); 241 ModCollector {
242 def_collector: &mut *self,
243 macro_depth: 0,
244 module_id,
245 file_id: file_id.into(),
246 item_tree: &item_tree,
247 mod_dir: ModDir::root(),
248 }
249 .collect(item_tree.top_level_items());
235 } 250 }
236 251
237 // main name resolution fixed-point loop. 252 // main name resolution fixed-point loop.
@@ -905,6 +920,8 @@ struct ModCollector<'a, 'b> {
905 920
906impl ModCollector<'_, '_> { 921impl ModCollector<'_, '_> {
907 fn collect(&mut self, items: &[ModItem]) { 922 fn collect(&mut self, items: &[ModItem]) {
923 let krate = self.def_collector.def_map.krate;
924
908 // Note: don't assert that inserted value is fresh: it's simply not true 925 // Note: don't assert that inserted value is fresh: it's simply not true
909 // for macros. 926 // for macros.
910 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); 927 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
@@ -921,11 +938,16 @@ impl ModCollector<'_, '_> {
921 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 938 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
922 // any other items. 939 // any other items.
923 for item in items { 940 for item in items {
924 let attrs = self.item_tree.attrs((*item).into()); 941 let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into());
925 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { 942 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
926 if let ModItem::ExternCrate(id) = item { 943 if let ModItem::ExternCrate(id) = item {
927 let import = self.item_tree[*id].clone(); 944 let import = self.item_tree[*id].clone();
928 if import.is_macro_use { 945 let attrs = self.item_tree.attrs(
946 self.def_collector.db,
947 krate,
948 ModItem::from(*id).into(),
949 );
950 if attrs.by_key("macro_use").exists() {
929 self.def_collector.import_macros_from_extern_crate(self.module_id, &import); 951 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
930 } 952 }
931 } 953 }
@@ -933,7 +955,7 @@ impl ModCollector<'_, '_> {
933 } 955 }
934 956
935 for &item in items { 957 for &item in items {
936 let attrs = self.item_tree.attrs(item.into()); 958 let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
937 if let Some(cfg) = attrs.cfg() { 959 if let Some(cfg) = attrs.cfg() {
938 if !self.is_cfg_enabled(&cfg) { 960 if !self.is_cfg_enabled(&cfg) {
939 self.emit_unconfigured_diagnostic(item, &cfg); 961 self.emit_unconfigured_diagnostic(item, &cfg);
@@ -946,11 +968,13 @@ impl ModCollector<'_, '_> {
946 968
947 let mut def = None; 969 let mut def = None;
948 match item { 970 match item {
949 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), 971 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
950 ModItem::Import(import_id) => { 972 ModItem::Import(import_id) => {
951 self.def_collector.unresolved_imports.push(ImportDirective { 973 self.def_collector.unresolved_imports.push(ImportDirective {
952 module_id: self.module_id, 974 module_id: self.module_id,
953 import: Import::from_use( 975 import: Import::from_use(
976 self.def_collector.db,
977 krate,
954 &self.item_tree, 978 &self.item_tree,
955 InFile::new(self.file_id, import_id), 979 InFile::new(self.file_id, import_id),
956 ), 980 ),
@@ -961,6 +985,8 @@ impl ModCollector<'_, '_> {
961 self.def_collector.unresolved_imports.push(ImportDirective { 985 self.def_collector.unresolved_imports.push(ImportDirective {
962 module_id: self.module_id, 986 module_id: self.module_id,
963 import: Import::from_extern_crate( 987 import: Import::from_extern_crate(
988 self.def_collector.db,
989 krate,
964 &self.item_tree, 990 &self.item_tree,
965 InFile::new(self.file_id, import_id), 991 InFile::new(self.file_id, import_id),
966 ), 992 ),
@@ -975,7 +1001,11 @@ impl ModCollector<'_, '_> {
975 1001
976 // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it 1002 // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it
977 // to define builtin macros, so we support at least that part. 1003 // to define builtin macros, so we support at least that part.
978 let attrs = self.item_tree.attrs(ModItem::from(id).into()); 1004 let attrs = self.item_tree.attrs(
1005 self.def_collector.db,
1006 krate,
1007 ModItem::from(id).into(),
1008 );
979 if attrs.by_key("rustc_builtin_macro").exists() { 1009 if attrs.by_key("rustc_builtin_macro").exists() {
980 let krate = self.def_collector.def_map.krate; 1010 let krate = self.def_collector.def_map.krate;
981 let macro_id = find_builtin_macro(&mac.name, krate, ast_id) 1011 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
@@ -1012,7 +1042,7 @@ impl ModCollector<'_, '_> {
1012 ModItem::Function(id) => { 1042 ModItem::Function(id) => {
1013 let func = &self.item_tree[id]; 1043 let func = &self.item_tree[id];
1014 1044
1015 self.collect_proc_macro_def(&func.name, attrs); 1045 self.collect_proc_macro_def(&func.name, &attrs);
1016 1046
1017 def = Some(DefData { 1047 def = Some(DefData {
1018 id: FunctionLoc { 1048 id: FunctionLoc {
@@ -1032,7 +1062,7 @@ impl ModCollector<'_, '_> {
1032 // FIXME: check attrs to see if this is an attribute macro invocation; 1062 // FIXME: check attrs to see if this is an attribute macro invocation;
1033 // in which case we don't add the invocation, just a single attribute 1063 // in which case we don't add the invocation, just a single attribute
1034 // macro invocation 1064 // macro invocation
1035 self.collect_derives(attrs, it.ast_id.upcast()); 1065 self.collect_derives(&attrs, it.ast_id.upcast());
1036 1066
1037 def = Some(DefData { 1067 def = Some(DefData {
1038 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } 1068 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) }
@@ -1049,7 +1079,7 @@ impl ModCollector<'_, '_> {
1049 // FIXME: check attrs to see if this is an attribute macro invocation; 1079 // FIXME: check attrs to see if this is an attribute macro invocation;
1050 // in which case we don't add the invocation, just a single attribute 1080 // in which case we don't add the invocation, just a single attribute
1051 // macro invocation 1081 // macro invocation
1052 self.collect_derives(attrs, it.ast_id.upcast()); 1082 self.collect_derives(&attrs, it.ast_id.upcast());
1053 1083
1054 def = Some(DefData { 1084 def = Some(DefData {
1055 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } 1085 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) }
@@ -1066,7 +1096,7 @@ impl ModCollector<'_, '_> {
1066 // FIXME: check attrs to see if this is an attribute macro invocation; 1096 // FIXME: check attrs to see if this is an attribute macro invocation;
1067 // in which case we don't add the invocation, just a single attribute 1097 // in which case we don't add the invocation, just a single attribute
1068 // macro invocation 1098 // macro invocation
1069 self.collect_derives(attrs, it.ast_id.upcast()); 1099 self.collect_derives(&attrs, it.ast_id.upcast());
1070 1100
1071 def = Some(DefData { 1101 def = Some(DefData {
1072 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } 1102 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) }
@@ -1259,20 +1289,20 @@ impl ModCollector<'_, '_> {
1259 } 1289 }
1260 1290
1261 fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) { 1291 fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) {
1262 for derive_subtree in attrs.by_key("derive").tt_values() { 1292 for derive in attrs.by_key("derive").attrs() {
1263 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree 1293 match derive.parse_derive() {
1264 for tt in &derive_subtree.token_trees { 1294 Some(derive_macros) => {
1265 let ident = match &tt { 1295 for path in derive_macros {
1266 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident, 1296 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1267 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok 1297 self.def_collector
1268 _ => continue, // anything else would be an error (which we currently ignore) 1298 .unexpanded_attribute_macros
1269 }; 1299 .push(DeriveDirective { module_id: self.module_id, ast_id });
1270 let path = ModPath::from_tt_ident(ident); 1300 }
1271 1301 }
1272 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); 1302 None => {
1273 self.def_collector 1303 // FIXME: diagnose
1274 .unexpanded_attribute_macros 1304 log::debug!("malformed derive: {:?}", derive);
1275 .push(DeriveDirective { module_id: self.module_id, ast_id }); 1305 }
1276 } 1306 }
1277 } 1307 }
1278 } 1308 }
@@ -1303,8 +1333,9 @@ impl ModCollector<'_, '_> {
1303 } 1333 }
1304 1334
1305 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { 1335 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
1336 let krate = self.def_collector.def_map.krate;
1306 let mac = &self.item_tree[id]; 1337 let mac = &self.item_tree[id];
1307 let attrs = self.item_tree.attrs(ModItem::from(id).into()); 1338 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1308 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); 1339 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1309 1340
1310 let export_attr = attrs.by_key("macro_export"); 1341 let export_attr = attrs.by_key("macro_export");
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index a4d1fb8f3..c459fa66d 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -13,8 +13,8 @@ use test_utils::mark;
13 13
14use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 14use crate::{db::DefDatabase, nameres::*, test_db::TestDB};
15 15
16fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { 16fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> {
17 let db = TestDB::with_files(fixture); 17 let db = TestDB::with_files(ra_fixture);
18 let krate = db.crate_graph().iter().next().unwrap(); 18 let krate = db.crate_graph().iter().next().unwrap();
19 db.crate_def_map(krate) 19 db.crate_def_map(krate)
20} 20}
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 1a7b98831..58d69d3c6 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -1,4 +1,5 @@
1use base_db::fixture::WithFixture; 1use base_db::fixture::WithFixture;
2use test_utils::mark;
2 3
3use crate::test_db::TestDB; 4use crate::test_db::TestDB;
4 5
@@ -119,3 +120,20 @@ fn inactive_item() {
119 "#, 120 "#,
120 ); 121 );
121} 122}
123
124/// Tests that `cfg` attributes behind `cfg_attr` is handled properly.
125#[test]
126fn inactive_via_cfg_attr() {
127 mark::check!(cfg_attr_active);
128 check_diagnostics(
129 r#"
130 //- /lib.rs
131 #[cfg_attr(not(never), cfg(no))] fn f() {}
132 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
133
134 #[cfg_attr(not(never), cfg(not(no)))] fn f() {}
135
136 #[cfg_attr(never, cfg(no))] fn g() {}
137 "#,
138 );
139}
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 6fe2ee78a..f9bf5bc72 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -632,11 +632,11 @@ pub struct bar;
632#[test] 632#[test]
633fn expand_derive() { 633fn expand_derive() {
634 let map = compute_crate_def_map( 634 let map = compute_crate_def_map(
635 " 635 r#"
636 //- /main.rs crate:main deps:core 636 //- /main.rs crate:main deps:core
637 use core::*; 637 use core::Copy;
638 638
639 #[derive(Copy, Clone)] 639 #[derive(Copy, core::Clone)]
640 struct Foo; 640 struct Foo;
641 641
642 //- /core.rs crate:core 642 //- /core.rs crate:core
@@ -645,7 +645,7 @@ fn expand_derive() {
645 645
646 #[rustc_builtin_macro] 646 #[rustc_builtin_macro]
647 pub macro Clone {} 647 pub macro Clone {}
648 ", 648 "#,
649 ); 649 );
650 assert_eq!(map.modules[map.root].scope.impls().len(), 2); 650 assert_eq!(map.modules[map.root].scope.impls().len(), 2);
651} 651}
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 00a69a8a6..e2bf85bbc 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -9,11 +9,8 @@ use std::{
9 9
10use crate::{body::LowerCtx, type_ref::LifetimeRef}; 10use crate::{body::LowerCtx, type_ref::LifetimeRef};
11use base_db::CrateId; 11use base_db::CrateId;
12use hir_expand::{ 12use hir_expand::{hygiene::Hygiene, name::Name};
13 hygiene::Hygiene, 13use syntax::ast;
14 name::{AsName, Name},
15};
16use syntax::ast::{self};
17 14
18use crate::{ 15use crate::{
19 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
@@ -56,11 +53,6 @@ impl ModPath {
56 ModPath { kind, segments } 53 ModPath { kind, segments }
57 } 54 }
58 55
59 /// Converts an `tt::Ident` into a single-identifier `Path`.
60 pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
61 ident.as_name().into()
62 }
63
64 /// Calls `cb` with all paths, represented by this use item. 56 /// Calls `cb` with all paths, represented by this use item.
65 pub(crate) fn expand_use_item( 57 pub(crate) fn expand_use_item(
66 item_src: InFile<ast::Use>, 58 item_src: InFile<ast::Use>,
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 7fb4caea3..2f44876a8 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -152,7 +152,9 @@ pub mod known {
152 str, 152 str,
153 // Special names 153 // Special names
154 macro_rules, 154 macro_rules,
155 derive,
155 doc, 156 doc,
157 cfg_attr,
156 // Components of known path (value or mod name) 158 // Components of known path (value or mod name)
157 std, 159 std,
158 core, 160 core,
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 8ad50a2ee..60e0cd4ad 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -181,8 +181,8 @@ fn caller() {
181 call<|>ee(); 181 call<|>ee();
182} 182}
183"#, 183"#,
184 "callee FN FileId(0) 0..14 3..9", 184 "callee Function FileId(0) 0..14 3..9",
185 &["caller FN FileId(0) 15..44 18..24 : [33..39]"], 185 &["caller Function FileId(0) 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 FileId(0) 0..14 3..9", 200 "callee Function FileId(0) 0..14 3..9",
201 &["caller FN FileId(0) 15..44 18..24 : [33..39]"], 201 &["caller Function FileId(0) 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 FileId(0) 0..14 3..9", 217 "callee Function FileId(0) 0..14 3..9",
218 &["caller FN FileId(0) 15..58 18..24 : [33..39, 47..53]"], 218 &["caller Function FileId(0) 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 FileId(0) 0..14 3..9", 237 "callee Function FileId(0) 0..14 3..9",
238 &[ 238 &[
239 "caller1 FN FileId(0) 15..45 18..25 : [34..40]", 239 "caller1 Function FileId(0) 15..45 18..25 : [34..40]",
240 "caller2 FN FileId(0) 47..77 50..57 : [66..72]", 240 "caller2 Function FileId(0) 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 FileId(0) 0..14 3..9", 266 "callee Function FileId(0) 0..14 3..9",
267 &[ 267 &[
268 "caller1 FN FileId(0) 15..45 18..25 : [34..40]", 268 "caller1 Function FileId(0) 15..45 18..25 : [34..40]",
269 "test_caller FN FileId(0) 95..149 110..121 : [134..140]", 269 "test_caller Function FileId(0) 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
288pub fn callee() {} 288pub fn callee() {}
289"#, 289"#,
290 "callee FN FileId(1) 0..18 7..13", 290 "callee Function FileId(1) 0..18 7..13",
291 &["caller FN FileId(0) 27..56 30..36 : [45..51]"], 291 &["caller Function FileId(0) 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 FileId(0) 15..58 18..24", 307 "caller Function FileId(0) 15..58 18..24",
308 &[], 308 &[],
309 &["callee FN FileId(0) 0..14 3..9 : [33..39, 47..53]"], 309 &["callee Function FileId(0) 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
326pub fn callee() {} 326pub fn callee() {}
327"#, 327"#,
328 "caller FN FileId(0) 27..56 30..36", 328 "caller Function FileId(0) 27..56 30..36",
329 &[], 329 &[],
330 &["callee FN FileId(1) 0..18 7..13 : [45..51]"], 330 &["callee Function FileId(1) 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 FileId(0) 33..64 36..43", 351 "caller2 Function FileId(0) 33..64 36..43",
352 &["caller1 FN FileId(0) 0..31 3..10 : [19..26]"], 352 &["caller1 Function FileId(0) 0..31 3..10 : [19..26]"],
353 &["caller3 FN FileId(0) 66..83 69..76 : [52..59]"], 353 &["caller3 Function FileId(0) 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 FileId(0) 0..18 3..4", 371 "a Function FileId(0) 0..18 3..4",
372 &["main FN FileId(0) 31..52 34..38 : [47..48]"], 372 &["main Function FileId(0) 31..52 34..38 : [47..48]"],
373 &["b FN FileId(0) 20..29 23..24 : [13..14]"], 373 &["b Function FileId(0) 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 FileId(0) 20..29 23..24", 388 "b Function FileId(0) 20..29 23..24",
389 &["a FN FileId(0) 0..18 3..4 : [13..14]"], 389 &["a Function FileId(0) 0..18 3..4 : [13..14]"],
390 &[], 390 &[],
391 ); 391 );
392 } 392 }
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index 13240672f..e8b896623 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -166,7 +166,7 @@ fn missing_record_expr_field_fix(
166 def_file_id = source.file_id; 166 def_file_id = source.file_id;
167 source.value.record_field_list()? 167 source.value.record_field_list()?
168 } 168 }
169 VariantDef::EnumVariant(e) => { 169 VariantDef::Variant(e) => {
170 module = e.module(sema.db); 170 module = e.module(sema.db);
171 let source = e.source(sema.db); 171 let source = e.source(sema.db);
172 def_file_id = source.file_id; 172 def_file_id = source.file_id;
diff --git a/crates/ide/src/display.rs b/crates/ide/src/display.rs
index 0650915c5..bae9e40df 100644
--- a/crates/ide/src/display.rs
+++ b/crates/ide/src/display.rs
@@ -1,10 +1,9 @@
1//! This module contains utilities for turning SyntaxNodes and HIR types 1//! This module contains utilities for turning SyntaxNodes and HIR types
2//! into types that may be used to render in a UI. 2//! into types that may be used to render in a UI.
3 3
4mod navigation_target; 4pub(crate) mod navigation_target;
5mod short_label; 5mod short_label;
6 6
7pub use navigation_target::NavigationTarget;
8pub(crate) use navigation_target::{ToNav, TryToNav}; 7pub(crate) use navigation_target::{ToNav, TryToNav};
9pub(crate) use short_label::ShortLabel; 8pub(crate) use short_label::ShortLabel;
10 9
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 54b33a98e..cd8ec54fa 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -1,28 +1,51 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::fmt;
4
3use either::Either; 5use either::Either;
4use hir::{ 6use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource};
5 AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirFileId, InFile, ModuleSource, 7use ide_db::{
8 base_db::{FileId, SourceDatabase},
9 symbol_index::FileSymbolKind,
6}; 10};
7use ide_db::base_db::{FileId, SourceDatabase};
8use ide_db::{defs::Definition, RootDatabase}; 11use ide_db::{defs::Definition, RootDatabase};
9use syntax::{ 12use syntax::{
10 ast::{self, NameOwner}, 13 ast::{self, NameOwner},
11 match_ast, AstNode, SmolStr, 14 match_ast, AstNode, SmolStr, TextRange,
12 SyntaxKind::{self, IDENT_PAT, LIFETIME_PARAM, TYPE_PARAM},
13 TextRange,
14}; 15};
15 16
16use crate::FileSymbol; 17use crate::FileSymbol;
17 18
18use super::short_label::ShortLabel; 19use super::short_label::ShortLabel;
19 20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
22pub enum SymbolKind {
23 Module,
24 Impl,
25 Field,
26 TypeParam,
27 LifetimeParam,
28 ValueParam,
29 SelfParam,
30 Local,
31 Function,
32 Const,
33 Static,
34 Struct,
35 Enum,
36 Variant,
37 Union,
38 TypeAlias,
39 Trait,
40 Macro,
41}
42
20/// `NavigationTarget` represents and element in the editor's UI which you can 43/// `NavigationTarget` represents and element in the editor's UI which you can
21/// click on to navigate to a particular piece of code. 44/// click on to navigate to a particular piece of code.
22/// 45///
23/// Typically, a `NavigationTarget` corresponds to some element in the source 46/// Typically, a `NavigationTarget` corresponds to some element in the source
24/// code, like a function or a struct, but this is not strictly required. 47/// code, like a function or a struct, but this is not strictly required.
25#[derive(Debug, Clone, PartialEq, Eq, Hash)] 48#[derive(Clone, PartialEq, Eq, Hash)]
26pub struct NavigationTarget { 49pub struct NavigationTarget {
27 pub file_id: FileId, 50 pub file_id: FileId,
28 /// Range which encompasses the whole element. 51 /// Range which encompasses the whole element.
@@ -42,12 +65,30 @@ pub struct NavigationTarget {
42 /// Clients should place the cursor on this range when navigating to this target. 65 /// Clients should place the cursor on this range when navigating to this target.
43 pub focus_range: Option<TextRange>, 66 pub focus_range: Option<TextRange>,
44 pub name: SmolStr, 67 pub name: SmolStr,
45 pub kind: SyntaxKind, 68 pub kind: Option<SymbolKind>,
46 pub container_name: Option<SmolStr>, 69 pub container_name: Option<SmolStr>,
47 pub description: Option<String>, 70 pub description: Option<String>,
48 pub docs: Option<Documentation>, 71 pub docs: Option<Documentation>,
49} 72}
50 73
74impl fmt::Debug for NavigationTarget {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 let mut f = f.debug_struct("NavigationTarget");
77 macro_rules! opt {
78 ($($name:ident)*) => {$(
79 if let Some(it) = &self.$name {
80 f.field(stringify!($name), it);
81 }
82 )*}
83 }
84 f.field("file_id", &self.file_id).field("full_range", &self.full_range);
85 opt!(focus_range);
86 f.field("name", &self.name);
87 opt!(kind container_name description docs);
88 f.finish()
89 }
90}
91
51pub(crate) trait ToNav { 92pub(crate) trait ToNav {
52 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget; 93 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget;
53} 94}
@@ -71,7 +112,7 @@ impl NavigationTarget {
71 name, 112 name,
72 None, 113 None,
73 frange.range, 114 frange.range,
74 src.value.syntax().kind(), 115 SymbolKind::Module,
75 ); 116 );
76 res.docs = module.attrs(db).docs(); 117 res.docs = module.attrs(db).docs();
77 res.description = src.value.short_label(); 118 res.description = src.value.short_label();
@@ -88,8 +129,13 @@ impl NavigationTarget {
88 129
89 #[cfg(test)] 130 #[cfg(test)]
90 pub(crate) fn debug_render(&self) -> String { 131 pub(crate) fn debug_render(&self) -> String {
91 let mut buf = 132 let mut buf = format!(
92 format!("{} {:?} {:?} {:?}", self.name, self.kind, self.file_id, self.full_range); 133 "{} {:?} {:?} {:?}",
134 self.name,
135 self.kind.unwrap(),
136 self.file_id,
137 self.full_range
138 );
93 if let Some(focus_range) = self.focus_range { 139 if let Some(focus_range) = self.focus_range {
94 buf.push_str(&format!(" {:?}", focus_range)) 140 buf.push_str(&format!(" {:?}", focus_range))
95 } 141 }
@@ -103,6 +149,7 @@ impl NavigationTarget {
103 pub(crate) fn from_named( 149 pub(crate) fn from_named(
104 db: &RootDatabase, 150 db: &RootDatabase,
105 node: InFile<&dyn ast::NameOwner>, 151 node: InFile<&dyn ast::NameOwner>,
152 kind: SymbolKind,
106 ) -> NavigationTarget { 153 ) -> NavigationTarget {
107 let name = 154 let name =
108 node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_")); 155 node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
@@ -110,32 +157,7 @@ impl NavigationTarget {
110 node.value.name().map(|it| node.with_value(it.syntax()).original_file_range(db).range); 157 node.value.name().map(|it| node.with_value(it.syntax()).original_file_range(db).range);
111 let frange = node.map(|it| it.syntax()).original_file_range(db); 158 let frange = node.map(|it| it.syntax()).original_file_range(db);
112 159
113 NavigationTarget::from_syntax( 160 NavigationTarget::from_syntax(frange.file_id, name, focus_range, frange.range, kind)
114 frange.file_id,
115 name,
116 focus_range,
117 frange.range,
118 node.value.syntax().kind(),
119 )
120 }
121
122 /// Allows `NavigationTarget` to be created from a `DocCommentsOwner` and a `NameOwner`
123 pub(crate) fn from_doc_commented(
124 db: &RootDatabase,
125 named: InFile<&dyn ast::NameOwner>,
126 node: InFile<&dyn ast::DocCommentsOwner>,
127 ) -> NavigationTarget {
128 let name =
129 named.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
130 let frange = node.map(|it| it.syntax()).original_file_range(db);
131
132 NavigationTarget::from_syntax(
133 frange.file_id,
134 name,
135 None,
136 frange.range,
137 node.value.syntax().kind(),
138 )
139 } 161 }
140 162
141 fn from_syntax( 163 fn from_syntax(
@@ -143,12 +165,12 @@ impl NavigationTarget {
143 name: SmolStr, 165 name: SmolStr,
144 focus_range: Option<TextRange>, 166 focus_range: Option<TextRange>,
145 full_range: TextRange, 167 full_range: TextRange,
146 kind: SyntaxKind, 168 kind: SymbolKind,
147 ) -> NavigationTarget { 169 ) -> NavigationTarget {
148 NavigationTarget { 170 NavigationTarget {
149 file_id, 171 file_id,
150 name, 172 name,
151 kind, 173 kind: Some(kind),
152 full_range, 174 full_range,
153 focus_range, 175 focus_range,
154 container_name: None, 176 container_name: None,
@@ -163,12 +185,22 @@ impl ToNav for FileSymbol {
163 NavigationTarget { 185 NavigationTarget {
164 file_id: self.file_id, 186 file_id: self.file_id,
165 name: self.name.clone(), 187 name: self.name.clone(),
166 kind: self.kind, 188 kind: Some(match self.kind {
189 FileSymbolKind::Function => SymbolKind::Function,
190 FileSymbolKind::Struct => SymbolKind::Struct,
191 FileSymbolKind::Enum => SymbolKind::Enum,
192 FileSymbolKind::Trait => SymbolKind::Trait,
193 FileSymbolKind::Module => SymbolKind::Module,
194 FileSymbolKind::TypeAlias => SymbolKind::TypeAlias,
195 FileSymbolKind::Const => SymbolKind::Const,
196 FileSymbolKind::Static => SymbolKind::Static,
197 FileSymbolKind::Macro => SymbolKind::Macro,
198 }),
167 full_range: self.range, 199 full_range: self.range,
168 focus_range: self.name_range, 200 focus_range: self.name_range,
169 container_name: self.container_name.clone(), 201 container_name: self.container_name.clone(),
170 description: description_from_symbol(db, self), 202 description: description_from_symbol(db, self),
171 docs: docs_from_symbol(db, self), 203 docs: None,
172 } 204 }
173 } 205 }
174} 206}
@@ -176,7 +208,15 @@ impl ToNav for FileSymbol {
176impl TryToNav for Definition { 208impl TryToNav for Definition {
177 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 209 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
178 match self { 210 match self {
179 Definition::Macro(it) => Some(it.to_nav(db)), 211 Definition::Macro(it) => {
212 // FIXME: Currently proc-macro do not have ast-node,
213 // such that it does not have source
214 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
215 if it.is_proc_macro() {
216 return None;
217 }
218 Some(it.to_nav(db))
219 }
180 Definition::Field(it) => Some(it.to_nav(db)), 220 Definition::Field(it) => Some(it.to_nav(db)),
181 Definition::ModuleDef(it) => it.try_to_nav(db), 221 Definition::ModuleDef(it) => it.try_to_nav(db),
182 Definition::SelfType(it) => Some(it.to_nav(db)), 222 Definition::SelfType(it) => Some(it.to_nav(db)),
@@ -193,7 +233,7 @@ impl TryToNav for hir::ModuleDef {
193 hir::ModuleDef::Module(it) => it.to_nav(db), 233 hir::ModuleDef::Module(it) => it.to_nav(db),
194 hir::ModuleDef::Function(it) => it.to_nav(db), 234 hir::ModuleDef::Function(it) => it.to_nav(db),
195 hir::ModuleDef::Adt(it) => it.to_nav(db), 235 hir::ModuleDef::Adt(it) => it.to_nav(db),
196 hir::ModuleDef::EnumVariant(it) => it.to_nav(db), 236 hir::ModuleDef::Variant(it) => it.to_nav(db),
197 hir::ModuleDef::Const(it) => it.to_nav(db), 237 hir::ModuleDef::Const(it) => it.to_nav(db),
198 hir::ModuleDef::Static(it) => it.to_nav(db), 238 hir::ModuleDef::Static(it) => it.to_nav(db),
199 hir::ModuleDef::Trait(it) => it.to_nav(db), 239 hir::ModuleDef::Trait(it) => it.to_nav(db),
@@ -204,16 +244,36 @@ impl TryToNav for hir::ModuleDef {
204 } 244 }
205} 245}
206 246
207pub(crate) trait ToNavFromAst {} 247pub(crate) trait ToNavFromAst {
208impl ToNavFromAst for hir::Function {} 248 const KIND: SymbolKind;
209impl ToNavFromAst for hir::Const {} 249}
210impl ToNavFromAst for hir::Static {} 250impl ToNavFromAst for hir::Function {
211impl ToNavFromAst for hir::Struct {} 251 const KIND: SymbolKind = SymbolKind::Function;
212impl ToNavFromAst for hir::Enum {} 252}
213impl ToNavFromAst for hir::EnumVariant {} 253impl ToNavFromAst for hir::Const {
214impl ToNavFromAst for hir::Union {} 254 const KIND: SymbolKind = SymbolKind::Const;
215impl ToNavFromAst for hir::TypeAlias {} 255}
216impl ToNavFromAst for hir::Trait {} 256impl ToNavFromAst for hir::Static {
257 const KIND: SymbolKind = SymbolKind::Static;
258}
259impl ToNavFromAst for hir::Struct {
260 const KIND: SymbolKind = SymbolKind::Struct;
261}
262impl ToNavFromAst for hir::Enum {
263 const KIND: SymbolKind = SymbolKind::Enum;
264}
265impl ToNavFromAst for hir::Variant {
266 const KIND: SymbolKind = SymbolKind::Variant;
267}
268impl ToNavFromAst for hir::Union {
269 const KIND: SymbolKind = SymbolKind::Union;
270}
271impl ToNavFromAst for hir::TypeAlias {
272 const KIND: SymbolKind = SymbolKind::TypeAlias;
273}
274impl ToNavFromAst for hir::Trait {
275 const KIND: SymbolKind = SymbolKind::Trait;
276}
217 277
218impl<D> ToNav for D 278impl<D> ToNav for D
219where 279where
@@ -222,8 +282,11 @@ where
222{ 282{
223 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 283 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
224 let src = self.source(db); 284 let src = self.source(db);
225 let mut res = 285 let mut res = NavigationTarget::from_named(
226 NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); 286 db,
287 src.as_ref().map(|it| it as &dyn ast::NameOwner),
288 D::KIND,
289 );
227 res.docs = self.docs(db); 290 res.docs = self.docs(db);
228 res.description = src.value.short_label(); 291 res.description = src.value.short_label();
229 res 292 res
@@ -241,7 +304,7 @@ impl ToNav for hir::Module {
241 } 304 }
242 }; 305 };
243 let frange = src.with_value(syntax).original_file_range(db); 306 let frange = src.with_value(syntax).original_file_range(db);
244 NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, syntax.kind()) 307 NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module)
245 } 308 }
246} 309}
247 310
@@ -265,7 +328,7 @@ impl ToNav for hir::Impl {
265 "impl".into(), 328 "impl".into(),
266 focus_range, 329 focus_range,
267 frange.range, 330 frange.range,
268 src.value.syntax().kind(), 331 SymbolKind::Impl,
269 ) 332 )
270 } 333 }
271} 334}
@@ -276,7 +339,8 @@ impl ToNav for hir::Field {
276 339
277 match &src.value { 340 match &src.value {
278 FieldSource::Named(it) => { 341 FieldSource::Named(it) => {
279 let mut res = NavigationTarget::from_named(db, src.with_value(it)); 342 let mut res =
343 NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
280 res.docs = self.docs(db); 344 res.docs = self.docs(db);
281 res.description = it.short_label(); 345 res.description = it.short_label();
282 res 346 res
@@ -288,7 +352,7 @@ impl ToNav for hir::Field {
288 "".into(), 352 "".into(),
289 None, 353 None,
290 frange.range, 354 frange.range,
291 it.syntax().kind(), 355 SymbolKind::Field,
292 ) 356 )
293 } 357 }
294 } 358 }
@@ -299,8 +363,11 @@ impl ToNav for hir::MacroDef {
299 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 363 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
300 let src = self.source(db); 364 let src = self.source(db);
301 log::debug!("nav target {:#?}", src.value.syntax()); 365 log::debug!("nav target {:#?}", src.value.syntax());
302 let mut res = 366 let mut res = NavigationTarget::from_named(
303 NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); 367 db,
368 src.as_ref().map(|it| it as &dyn ast::NameOwner),
369 SymbolKind::Macro,
370 );
304 res.docs = self.docs(db); 371 res.docs = self.docs(db);
305 res 372 res
306 } 373 }
@@ -340,10 +407,11 @@ impl ToNav for hir::Local {
340 Some(it) => it.to_string().into(), 407 Some(it) => it.to_string().into(),
341 None => "".into(), 408 None => "".into(),
342 }; 409 };
410 let kind = if self.is_param(db) { SymbolKind::ValueParam } else { SymbolKind::Local };
343 NavigationTarget { 411 NavigationTarget {
344 file_id: full_range.file_id, 412 file_id: full_range.file_id,
345 name, 413 name,
346 kind: IDENT_PAT, 414 kind: Some(kind),
347 full_range: full_range.range, 415 full_range: full_range.range,
348 focus_range: None, 416 focus_range: None,
349 container_name: None, 417 container_name: None,
@@ -367,7 +435,7 @@ impl ToNav for hir::TypeParam {
367 NavigationTarget { 435 NavigationTarget {
368 file_id: src.file_id.original_file(db), 436 file_id: src.file_id.original_file(db),
369 name: self.name(db).to_string().into(), 437 name: self.name(db).to_string().into(),
370 kind: TYPE_PARAM, 438 kind: Some(SymbolKind::TypeParam),
371 full_range, 439 full_range,
372 focus_range, 440 focus_range,
373 container_name: None, 441 container_name: None,
@@ -384,7 +452,7 @@ impl ToNav for hir::LifetimeParam {
384 NavigationTarget { 452 NavigationTarget {
385 file_id: src.file_id.original_file(db), 453 file_id: src.file_id.original_file(db),
386 name: self.name(db).to_string().into(), 454 name: self.name(db).to_string().into(),
387 kind: LIFETIME_PARAM, 455 kind: Some(SymbolKind::LifetimeParam),
388 full_range, 456 full_range,
389 focus_range: Some(full_range), 457 focus_range: Some(full_range),
390 container_name: None, 458 container_name: None,
@@ -394,30 +462,6 @@ impl ToNav for hir::LifetimeParam {
394 } 462 }
395} 463}
396 464
397pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<Documentation> {
398 let parse = db.parse(symbol.file_id);
399 let node = symbol.ptr.to_node(parse.tree().syntax());
400 let file_id = HirFileId::from(symbol.file_id);
401
402 let it = match_ast! {
403 match node {
404 ast::Fn(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
405 ast::Struct(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
406 ast::Enum(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
407 ast::Trait(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
408 ast::Module(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
409 ast::TypeAlias(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
410 ast::Const(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
411 ast::Static(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
412 ast::RecordField(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
413 ast::Variant(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
414 ast::MacroCall(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
415 _ => return None,
416 }
417 };
418 it.docs()
419}
420
421/// Get a description of a symbol. 465/// Get a description of a symbol.
422/// 466///
423/// e.g. `struct Name`, `enum Name`, `fn Name` 467/// e.g. `struct Name`, `enum Name`, `fn Name`
@@ -465,34 +509,21 @@ fn foo() { enum FooInner { } }
465 0, 509 0,
466 ), 510 ),
467 full_range: 0..17, 511 full_range: 0..17,
468 focus_range: Some( 512 focus_range: 5..13,
469 5..13,
470 ),
471 name: "FooInner", 513 name: "FooInner",
472 kind: ENUM, 514 kind: Enum,
473 container_name: None, 515 description: "enum FooInner",
474 description: Some(
475 "enum FooInner",
476 ),
477 docs: None,
478 }, 516 },
479 NavigationTarget { 517 NavigationTarget {
480 file_id: FileId( 518 file_id: FileId(
481 0, 519 0,
482 ), 520 ),
483 full_range: 29..46, 521 full_range: 29..46,
484 focus_range: Some( 522 focus_range: 34..42,
485 34..42,
486 ),
487 name: "FooInner", 523 name: "FooInner",
488 kind: ENUM, 524 kind: Enum,
489 container_name: Some( 525 container_name: "foo",
490 "foo", 526 description: "enum FooInner",
491 ),
492 description: Some(
493 "enum FooInner",
494 ),
495 docs: None,
496 }, 527 },
497 ] 528 ]
498 "#]] 529 "#]]
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 79c081cac..b61ea0b3e 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -181,7 +181,7 @@ fn rewrite_intra_doc_link(
181 ModuleDef::Module(it) => it.resolve_doc_path(db, link, ns), 181 ModuleDef::Module(it) => it.resolve_doc_path(db, link, ns),
182 ModuleDef::Function(it) => it.resolve_doc_path(db, link, ns), 182 ModuleDef::Function(it) => it.resolve_doc_path(db, link, ns),
183 ModuleDef::Adt(it) => it.resolve_doc_path(db, link, ns), 183 ModuleDef::Adt(it) => it.resolve_doc_path(db, link, ns),
184 ModuleDef::EnumVariant(it) => it.resolve_doc_path(db, link, ns), 184 ModuleDef::Variant(it) => it.resolve_doc_path(db, link, ns),
185 ModuleDef::Const(it) => it.resolve_doc_path(db, link, ns), 185 ModuleDef::Const(it) => it.resolve_doc_path(db, link, ns),
186 ModuleDef::Static(it) => it.resolve_doc_path(db, link, ns), 186 ModuleDef::Static(it) => it.resolve_doc_path(db, link, ns),
187 ModuleDef::Trait(it) => it.resolve_doc_path(db, link, ns), 187 ModuleDef::Trait(it) => it.resolve_doc_path(db, link, ns),
@@ -390,7 +390,7 @@ fn get_symbol_filename(db: &dyn HirDatabase, definition: &ModuleDef) -> Option<S
390 ModuleDef::TypeAlias(t) => format!("type.{}.html", t.name(db)), 390 ModuleDef::TypeAlias(t) => format!("type.{}.html", t.name(db)),
391 ModuleDef::BuiltinType(t) => format!("primitive.{}.html", t.as_name()), 391 ModuleDef::BuiltinType(t) => format!("primitive.{}.html", t.as_name()),
392 ModuleDef::Function(f) => format!("fn.{}.html", f.name(db)), 392 ModuleDef::Function(f) => format!("fn.{}.html", f.name(db)),
393 ModuleDef::EnumVariant(ev) => { 393 ModuleDef::Variant(ev) => {
394 format!("enum.{}.html#variant.{}", ev.parent_enum(db).name(db), ev.name(db)) 394 format!("enum.{}.html#variant.{}", ev.parent_enum(db).name(db), ev.name(db))
395 } 395 }
396 ModuleDef::Const(c) => format!("const.{}.html", c.name(db)?), 396 ModuleDef::Const(c) => format!("const.{}.html", c.name(db)?),
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index c51531391..32556dad3 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -1,15 +1,17 @@
1use syntax::{ 1use syntax::{
2 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner}, 2 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
3 match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent, 3 match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent,
4}; 4};
5 5
6use crate::SymbolKind;
7
6#[derive(Debug, Clone)] 8#[derive(Debug, Clone)]
7pub struct StructureNode { 9pub struct StructureNode {
8 pub parent: Option<usize>, 10 pub parent: Option<usize>,
9 pub label: String, 11 pub label: String,
10 pub navigation_range: TextRange, 12 pub navigation_range: TextRange,
11 pub node_range: TextRange, 13 pub node_range: TextRange,
12 pub kind: SyntaxKind, 14 pub kind: SymbolKind,
13 pub detail: Option<String>, 15 pub detail: Option<String>,
14 pub deprecated: bool, 16 pub deprecated: bool,
15} 17}
@@ -51,25 +53,27 @@ pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
51} 53}
52 54
53fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { 55fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
54 fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> { 56 fn decl<N: NameOwner + AttrsOwner>(node: N, kind: SymbolKind) -> Option<StructureNode> {
55 decl_with_detail(&node, None) 57 decl_with_detail(&node, None, kind)
56 } 58 }
57 59
58 fn decl_with_type_ref<N: NameOwner + AttrsOwner>( 60 fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
59 node: &N, 61 node: &N,
60 type_ref: Option<ast::Type>, 62 type_ref: Option<ast::Type>,
63 kind: SymbolKind,
61 ) -> Option<StructureNode> { 64 ) -> Option<StructureNode> {
62 let detail = type_ref.map(|type_ref| { 65 let detail = type_ref.map(|type_ref| {
63 let mut detail = String::new(); 66 let mut detail = String::new();
64 collapse_ws(type_ref.syntax(), &mut detail); 67 collapse_ws(type_ref.syntax(), &mut detail);
65 detail 68 detail
66 }); 69 });
67 decl_with_detail(node, detail) 70 decl_with_detail(node, detail, kind)
68 } 71 }
69 72
70 fn decl_with_detail<N: NameOwner + AttrsOwner>( 73 fn decl_with_detail<N: NameOwner + AttrsOwner>(
71 node: &N, 74 node: &N,
72 detail: Option<String>, 75 detail: Option<String>,
76 kind: SymbolKind,
73 ) -> Option<StructureNode> { 77 ) -> Option<StructureNode> {
74 let name = node.name()?; 78 let name = node.name()?;
75 79
@@ -78,7 +82,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
78 label: name.text().to_string(), 82 label: name.text().to_string(),
79 navigation_range: name.syntax().text_range(), 83 navigation_range: name.syntax().text_range(),
80 node_range: node.syntax().text_range(), 84 node_range: node.syntax().text_range(),
81 kind: node.syntax().kind(), 85 kind,
82 detail, 86 detail,
83 deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"), 87 deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"),
84 }) 88 })
@@ -117,18 +121,18 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
117 collapse_ws(ret_type.syntax(), &mut detail); 121 collapse_ws(ret_type.syntax(), &mut detail);
118 } 122 }
119 123
120 decl_with_detail(&it, Some(detail)) 124 decl_with_detail(&it, Some(detail), SymbolKind::Function)
121 }, 125 },
122 ast::Struct(it) => decl(it), 126 ast::Struct(it) => decl(it, SymbolKind::Struct),
123 ast::Union(it) => decl(it), 127 ast::Union(it) => decl(it, SymbolKind::Union),
124 ast::Enum(it) => decl(it), 128 ast::Enum(it) => decl(it, SymbolKind::Enum),
125 ast::Variant(it) => decl(it), 129 ast::Variant(it) => decl(it, SymbolKind::Variant),
126 ast::Trait(it) => decl(it), 130 ast::Trait(it) => decl(it, SymbolKind::Trait),
127 ast::Module(it) => decl(it), 131 ast::Module(it) => decl(it, SymbolKind::Module),
128 ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty()), 132 ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::TypeAlias),
129 ast::RecordField(it) => decl_with_type_ref(&it, it.ty()), 133 ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Field),
130 ast::Const(it) => decl_with_type_ref(&it, it.ty()), 134 ast::Const(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Const),
131 ast::Static(it) => decl_with_type_ref(&it, it.ty()), 135 ast::Static(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Static),
132 ast::Impl(it) => { 136 ast::Impl(it) => {
133 let target_type = it.self_ty()?; 137 let target_type = it.self_ty()?;
134 let target_trait = it.trait_(); 138 let target_trait = it.trait_();
@@ -144,13 +148,13 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
144 label, 148 label,
145 navigation_range: target_type.syntax().text_range(), 149 navigation_range: target_type.syntax().text_range(),
146 node_range: it.syntax().text_range(), 150 node_range: it.syntax().text_range(),
147 kind: it.syntax().kind(), 151 kind: SymbolKind::Impl,
148 detail: None, 152 detail: None,
149 deprecated: false, 153 deprecated: false,
150 }; 154 };
151 Some(node) 155 Some(node)
152 }, 156 },
153 ast::MacroRules(it) => decl(it), 157 ast::MacroRules(it) => decl(it, SymbolKind::Macro),
154 _ => None, 158 _ => None,
155 } 159 }
156 } 160 }
@@ -222,7 +226,7 @@ fn very_obsolete() {}
222 label: "Foo", 226 label: "Foo",
223 navigation_range: 8..11, 227 navigation_range: 8..11,
224 node_range: 1..26, 228 node_range: 1..26,
225 kind: STRUCT, 229 kind: Struct,
226 detail: None, 230 detail: None,
227 deprecated: false, 231 deprecated: false,
228 }, 232 },
@@ -233,7 +237,7 @@ fn very_obsolete() {}
233 label: "x", 237 label: "x",
234 navigation_range: 18..19, 238 navigation_range: 18..19,
235 node_range: 18..24, 239 node_range: 18..24,
236 kind: RECORD_FIELD, 240 kind: Field,
237 detail: Some( 241 detail: Some(
238 "i32", 242 "i32",
239 ), 243 ),
@@ -244,7 +248,7 @@ fn very_obsolete() {}
244 label: "m", 248 label: "m",
245 navigation_range: 32..33, 249 navigation_range: 32..33,
246 node_range: 28..158, 250 node_range: 28..158,
247 kind: MODULE, 251 kind: Module,
248 detail: None, 252 detail: None,
249 deprecated: false, 253 deprecated: false,
250 }, 254 },
@@ -255,7 +259,7 @@ fn very_obsolete() {}
255 label: "bar1", 259 label: "bar1",
256 navigation_range: 43..47, 260 navigation_range: 43..47,
257 node_range: 40..52, 261 node_range: 40..52,
258 kind: FN, 262 kind: Function,
259 detail: Some( 263 detail: Some(
260 "fn()", 264 "fn()",
261 ), 265 ),
@@ -268,7 +272,7 @@ fn very_obsolete() {}
268 label: "bar2", 272 label: "bar2",
269 navigation_range: 60..64, 273 navigation_range: 60..64,
270 node_range: 57..81, 274 node_range: 57..81,
271 kind: FN, 275 kind: Function,
272 detail: Some( 276 detail: Some(
273 "fn<T>(t: T) -> T", 277 "fn<T>(t: T) -> T",
274 ), 278 ),
@@ -281,7 +285,7 @@ fn very_obsolete() {}
281 label: "bar3", 285 label: "bar3",
282 navigation_range: 89..93, 286 navigation_range: 89..93,
283 node_range: 86..156, 287 node_range: 86..156,
284 kind: FN, 288 kind: Function,
285 detail: Some( 289 detail: Some(
286 "fn<A, B>(a: A, b: B) -> Vec< u32 >", 290 "fn<A, B>(a: A, b: B) -> Vec< u32 >",
287 ), 291 ),
@@ -292,7 +296,7 @@ fn very_obsolete() {}
292 label: "E", 296 label: "E",
293 navigation_range: 165..166, 297 navigation_range: 165..166,
294 node_range: 160..180, 298 node_range: 160..180,
295 kind: ENUM, 299 kind: Enum,
296 detail: None, 300 detail: None,
297 deprecated: false, 301 deprecated: false,
298 }, 302 },
@@ -303,7 +307,7 @@ fn very_obsolete() {}
303 label: "X", 307 label: "X",
304 navigation_range: 169..170, 308 navigation_range: 169..170,
305 node_range: 169..170, 309 node_range: 169..170,
306 kind: VARIANT, 310 kind: Variant,
307 detail: None, 311 detail: None,
308 deprecated: false, 312 deprecated: false,
309 }, 313 },
@@ -314,7 +318,7 @@ fn very_obsolete() {}
314 label: "Y", 318 label: "Y",
315 navigation_range: 172..173, 319 navigation_range: 172..173,
316 node_range: 172..178, 320 node_range: 172..178,
317 kind: VARIANT, 321 kind: Variant,
318 detail: None, 322 detail: None,
319 deprecated: false, 323 deprecated: false,
320 }, 324 },
@@ -323,7 +327,7 @@ fn very_obsolete() {}
323 label: "T", 327 label: "T",
324 navigation_range: 186..187, 328 navigation_range: 186..187,
325 node_range: 181..193, 329 node_range: 181..193,
326 kind: TYPE_ALIAS, 330 kind: TypeAlias,
327 detail: Some( 331 detail: Some(
328 "()", 332 "()",
329 ), 333 ),
@@ -334,7 +338,7 @@ fn very_obsolete() {}
334 label: "S", 338 label: "S",
335 navigation_range: 201..202, 339 navigation_range: 201..202,
336 node_range: 194..213, 340 node_range: 194..213,
337 kind: STATIC, 341 kind: Static,
338 detail: Some( 342 detail: Some(
339 "i32", 343 "i32",
340 ), 344 ),
@@ -345,7 +349,7 @@ fn very_obsolete() {}
345 label: "C", 349 label: "C",
346 navigation_range: 220..221, 350 navigation_range: 220..221,
347 node_range: 214..232, 351 node_range: 214..232,
348 kind: CONST, 352 kind: Const,
349 detail: Some( 353 detail: Some(
350 "i32", 354 "i32",
351 ), 355 ),
@@ -356,7 +360,7 @@ fn very_obsolete() {}
356 label: "impl E", 360 label: "impl E",
357 navigation_range: 239..240, 361 navigation_range: 239..240,
358 node_range: 234..243, 362 node_range: 234..243,
359 kind: IMPL, 363 kind: Impl,
360 detail: None, 364 detail: None,
361 deprecated: false, 365 deprecated: false,
362 }, 366 },
@@ -365,7 +369,7 @@ fn very_obsolete() {}
365 label: "impl fmt::Debug for E", 369 label: "impl fmt::Debug for E",
366 navigation_range: 265..266, 370 navigation_range: 265..266,
367 node_range: 245..269, 371 node_range: 245..269,
368 kind: IMPL, 372 kind: Impl,
369 detail: None, 373 detail: None,
370 deprecated: false, 374 deprecated: false,
371 }, 375 },
@@ -374,7 +378,7 @@ fn very_obsolete() {}
374 label: "mc", 378 label: "mc",
375 navigation_range: 284..286, 379 navigation_range: 284..286,
376 node_range: 271..303, 380 node_range: 271..303,
377 kind: MACRO_RULES, 381 kind: Macro,
378 detail: None, 382 detail: None,
379 deprecated: false, 383 deprecated: false,
380 }, 384 },
@@ -383,7 +387,7 @@ fn very_obsolete() {}
383 label: "mcexp", 387 label: "mcexp",
384 navigation_range: 334..339, 388 navigation_range: 334..339,
385 node_range: 305..356, 389 node_range: 305..356,
386 kind: MACRO_RULES, 390 kind: Macro,
387 detail: None, 391 detail: None,
388 deprecated: false, 392 deprecated: false,
389 }, 393 },
@@ -392,7 +396,7 @@ fn very_obsolete() {}
392 label: "mcexp", 396 label: "mcexp",
393 navigation_range: 387..392, 397 navigation_range: 387..392,
394 node_range: 358..409, 398 node_range: 358..409,
395 kind: MACRO_RULES, 399 kind: Macro,
396 detail: None, 400 detail: None,
397 deprecated: false, 401 deprecated: false,
398 }, 402 },
@@ -401,7 +405,7 @@ fn very_obsolete() {}
401 label: "obsolete", 405 label: "obsolete",
402 navigation_range: 428..436, 406 navigation_range: 428..436,
403 node_range: 411..441, 407 node_range: 411..441,
404 kind: FN, 408 kind: Function,
405 detail: Some( 409 detail: Some(
406 "fn()", 410 "fn()",
407 ), 411 ),
@@ -412,7 +416,7 @@ fn very_obsolete() {}
412 label: "very_obsolete", 416 label: "very_obsolete",
413 navigation_range: 481..494, 417 navigation_range: 481..494,
414 node_range: 443..499, 418 node_range: 443..499,
415 kind: FN, 419 kind: Function,
416 detail: Some( 420 detail: Some(
417 "fn()", 421 "fn()",
418 ), 422 ),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index d75ae447b..431da5d9c 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -9,7 +9,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset,
9 9
10use crate::{ 10use crate::{
11 display::{ToNav, TryToNav}, 11 display::{ToNav, TryToNav},
12 FilePosition, NavigationTarget, RangeInfo, 12 FilePosition, NavigationTarget, RangeInfo, SymbolKind,
13}; 13};
14 14
15// Feature: Go to Definition 15// Feature: Go to Definition
@@ -86,7 +86,7 @@ fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<Nav
86 full_range: self_param.syntax().text_range(), 86 full_range: self_param.syntax().text_range(),
87 focus_range: Some(self_token.text_range()), 87 focus_range: Some(self_token.text_range()),
88 name: self_token.text().clone(), 88 name: self_token.text().clone(),
89 kind: self_token.kind(), 89 kind: Some(SymbolKind::SelfParam),
90 container_name: None, 90 container_name: None,
91 description: None, 91 description: None,
92 docs: None, 92 docs: None,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index e82aad6d5..52f993cc9 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -297,7 +297,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
297 AssocItemContainer::Trait(t) => Some(t.name(db)), 297 AssocItemContainer::Trait(t) => Some(t.name(db)),
298 AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)), 298 AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
299 }, 299 },
300 ModuleDef::EnumVariant(e) => Some(e.parent_enum(db).name(db)), 300 ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
301 _ => None, 301 _ => None,
302 }, 302 },
303 _ => None, 303 _ => None,
@@ -324,6 +324,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
324 let mod_path = definition_mod_path(db, &def); 324 let mod_path = definition_mod_path(db, &def);
325 return match def { 325 return match def {
326 Definition::Macro(it) => { 326 Definition::Macro(it) => {
327 // FIXME: Currently proc-macro do not have ast-node,
328 // such that it does not have source
329 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
330 if it.is_proc_macro() {
331 return None;
332 }
327 let label = macro_label(&it.source(db).value); 333 let label = macro_label(&it.source(db).value);
328 from_def_source_labeled(db, it, Some(label), mod_path) 334 from_def_source_labeled(db, it, Some(label), mod_path)
329 } 335 }
@@ -349,7 +355,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
349 ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), 355 ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
350 ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path), 356 ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
351 ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path), 357 ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
352 ModuleDef::EnumVariant(it) => from_def_source(db, it, mod_path), 358 ModuleDef::Variant(it) => from_def_source(db, it, mod_path),
353 ModuleDef::Const(it) => from_def_source(db, it, mod_path), 359 ModuleDef::Const(it) => from_def_source(db, it, mod_path),
354 ModuleDef::Static(it) => from_def_source(db, it, mod_path), 360 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
355 ModuleDef::Trait(it) => from_def_source(db, it, mod_path), 361 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
@@ -2181,14 +2187,9 @@ fn foo_<|>test() {}
2181 0, 2187 0,
2182 ), 2188 ),
2183 full_range: 0..24, 2189 full_range: 0..24,
2184 focus_range: Some( 2190 focus_range: 11..19,
2185 11..19,
2186 ),
2187 name: "foo_test", 2191 name: "foo_test",
2188 kind: FN, 2192 kind: Function,
2189 container_name: None,
2190 description: None,
2191 docs: None,
2192 }, 2193 },
2193 kind: Test { 2194 kind: Test {
2194 test_id: Path( 2195 test_id: Path(
@@ -2224,14 +2225,9 @@ mod tests<|> {
2224 0, 2225 0,
2225 ), 2226 ),
2226 full_range: 0..46, 2227 full_range: 0..46,
2227 focus_range: Some( 2228 focus_range: 4..9,
2228 4..9,
2229 ),
2230 name: "tests", 2229 name: "tests",
2231 kind: MODULE, 2230 kind: Module,
2232 container_name: None,
2233 description: None,
2234 docs: None,
2235 }, 2231 },
2236 kind: TestMod { 2232 kind: TestMod {
2237 path: "tests", 2233 path: "tests",
@@ -2263,16 +2259,10 @@ fn main() { let s<|>t = S{ f1:0 }; }
2263 0, 2259 0,
2264 ), 2260 ),
2265 full_range: 0..19, 2261 full_range: 0..19,
2266 focus_range: Some( 2262 focus_range: 7..8,
2267 7..8,
2268 ),
2269 name: "S", 2263 name: "S",
2270 kind: STRUCT, 2264 kind: Struct,
2271 container_name: None, 2265 description: "struct S",
2272 description: Some(
2273 "struct S",
2274 ),
2275 docs: None,
2276 }, 2266 },
2277 }, 2267 },
2278 ], 2268 ],
@@ -2302,16 +2292,10 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
2302 0, 2292 0,
2303 ), 2293 ),
2304 full_range: 17..37, 2294 full_range: 17..37,
2305 focus_range: Some( 2295 focus_range: 24..25,
2306 24..25,
2307 ),
2308 name: "S", 2296 name: "S",
2309 kind: STRUCT, 2297 kind: Struct,
2310 container_name: None, 2298 description: "struct S",
2311 description: Some(
2312 "struct S",
2313 ),
2314 docs: None,
2315 }, 2299 },
2316 }, 2300 },
2317 HoverGotoTypeData { 2301 HoverGotoTypeData {
@@ -2321,16 +2305,10 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
2321 0, 2305 0,
2322 ), 2306 ),
2323 full_range: 0..16, 2307 full_range: 0..16,
2324 focus_range: Some( 2308 focus_range: 7..10,
2325 7..10,
2326 ),
2327 name: "Arg", 2309 name: "Arg",
2328 kind: STRUCT, 2310 kind: Struct,
2329 container_name: None, 2311 description: "struct Arg",
2330 description: Some(
2331 "struct Arg",
2332 ),
2333 docs: None,
2334 }, 2312 },
2335 }, 2313 },
2336 ], 2314 ],
@@ -2360,16 +2338,10 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
2360 0, 2338 0,
2361 ), 2339 ),
2362 full_range: 17..37, 2340 full_range: 17..37,
2363 focus_range: Some( 2341 focus_range: 24..25,
2364 24..25,
2365 ),
2366 name: "S", 2342 name: "S",
2367 kind: STRUCT, 2343 kind: Struct,
2368 container_name: None, 2344 description: "struct S",
2369 description: Some(
2370 "struct S",
2371 ),
2372 docs: None,
2373 }, 2345 },
2374 }, 2346 },
2375 HoverGotoTypeData { 2347 HoverGotoTypeData {
@@ -2379,16 +2351,10 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
2379 0, 2351 0,
2380 ), 2352 ),
2381 full_range: 0..16, 2353 full_range: 0..16,
2382 focus_range: Some( 2354 focus_range: 7..10,
2383 7..10,
2384 ),
2385 name: "Arg", 2355 name: "Arg",
2386 kind: STRUCT, 2356 kind: Struct,
2387 container_name: None, 2357 description: "struct Arg",
2388 description: Some(
2389 "struct Arg",
2390 ),
2391 docs: None,
2392 }, 2358 },
2393 }, 2359 },
2394 ], 2360 ],
@@ -2421,16 +2387,10 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2421 0, 2387 0,
2422 ), 2388 ),
2423 full_range: 0..14, 2389 full_range: 0..14,
2424 focus_range: Some( 2390 focus_range: 7..8,
2425 7..8,
2426 ),
2427 name: "A", 2391 name: "A",
2428 kind: STRUCT, 2392 kind: Struct,
2429 container_name: None, 2393 description: "struct A",
2430 description: Some(
2431 "struct A",
2432 ),
2433 docs: None,
2434 }, 2394 },
2435 }, 2395 },
2436 HoverGotoTypeData { 2396 HoverGotoTypeData {
@@ -2440,16 +2400,10 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2440 0, 2400 0,
2441 ), 2401 ),
2442 full_range: 15..29, 2402 full_range: 15..29,
2443 focus_range: Some( 2403 focus_range: 22..23,
2444 22..23,
2445 ),
2446 name: "B", 2404 name: "B",
2447 kind: STRUCT, 2405 kind: Struct,
2448 container_name: None, 2406 description: "struct B",
2449 description: Some(
2450 "struct B",
2451 ),
2452 docs: None,
2453 }, 2407 },
2454 }, 2408 },
2455 HoverGotoTypeData { 2409 HoverGotoTypeData {
@@ -2459,16 +2413,10 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2459 0, 2413 0,
2460 ), 2414 ),
2461 full_range: 42..60, 2415 full_range: 42..60,
2462 focus_range: Some( 2416 focus_range: 53..54,
2463 53..54,
2464 ),
2465 name: "C", 2417 name: "C",
2466 kind: STRUCT, 2418 kind: Struct,
2467 container_name: None, 2419 description: "pub struct C",
2468 description: Some(
2469 "pub struct C",
2470 ),
2471 docs: None,
2472 }, 2420 },
2473 }, 2421 },
2474 ], 2422 ],
@@ -2498,16 +2446,10 @@ fn main() { let s<|>t = foo(); }
2498 0, 2446 0,
2499 ), 2447 ),
2500 full_range: 0..12, 2448 full_range: 0..12,
2501 focus_range: Some( 2449 focus_range: 6..9,
2502 6..9,
2503 ),
2504 name: "Foo", 2450 name: "Foo",
2505 kind: TRAIT, 2451 kind: Trait,
2506 container_name: None, 2452 description: "trait Foo",
2507 description: Some(
2508 "trait Foo",
2509 ),
2510 docs: None,
2511 }, 2453 },
2512 }, 2454 },
2513 ], 2455 ],
@@ -2538,16 +2480,10 @@ fn main() { let s<|>t = foo(); }
2538 0, 2480 0,
2539 ), 2481 ),
2540 full_range: 0..15, 2482 full_range: 0..15,
2541 focus_range: Some( 2483 focus_range: 6..9,
2542 6..9,
2543 ),
2544 name: "Foo", 2484 name: "Foo",
2545 kind: TRAIT, 2485 kind: Trait,
2546 container_name: None, 2486 description: "trait Foo",
2547 description: Some(
2548 "trait Foo",
2549 ),
2550 docs: None,
2551 }, 2487 },
2552 }, 2488 },
2553 HoverGotoTypeData { 2489 HoverGotoTypeData {
@@ -2557,16 +2493,10 @@ fn main() { let s<|>t = foo(); }
2557 0, 2493 0,
2558 ), 2494 ),
2559 full_range: 16..25, 2495 full_range: 16..25,
2560 focus_range: Some( 2496 focus_range: 23..24,
2561 23..24,
2562 ),
2563 name: "S", 2497 name: "S",
2564 kind: STRUCT, 2498 kind: Struct,
2565 container_name: None, 2499 description: "struct S",
2566 description: Some(
2567 "struct S",
2568 ),
2569 docs: None,
2570 }, 2500 },
2571 }, 2501 },
2572 ], 2502 ],
@@ -2597,16 +2527,10 @@ fn main() { let s<|>t = foo(); }
2597 0, 2527 0,
2598 ), 2528 ),
2599 full_range: 0..12, 2529 full_range: 0..12,
2600 focus_range: Some( 2530 focus_range: 6..9,
2601 6..9,
2602 ),
2603 name: "Foo", 2531 name: "Foo",
2604 kind: TRAIT, 2532 kind: Trait,
2605 container_name: None, 2533 description: "trait Foo",
2606 description: Some(
2607 "trait Foo",
2608 ),
2609 docs: None,
2610 }, 2534 },
2611 }, 2535 },
2612 HoverGotoTypeData { 2536 HoverGotoTypeData {
@@ -2616,16 +2540,10 @@ fn main() { let s<|>t = foo(); }
2616 0, 2540 0,
2617 ), 2541 ),
2618 full_range: 13..25, 2542 full_range: 13..25,
2619 focus_range: Some( 2543 focus_range: 19..22,
2620 19..22,
2621 ),
2622 name: "Bar", 2544 name: "Bar",
2623 kind: TRAIT, 2545 kind: Trait,
2624 container_name: None, 2546 description: "trait Bar",
2625 description: Some(
2626 "trait Bar",
2627 ),
2628 docs: None,
2629 }, 2547 },
2630 }, 2548 },
2631 ], 2549 ],
@@ -2659,16 +2577,10 @@ fn main() { let s<|>t = foo(); }
2659 0, 2577 0,
2660 ), 2578 ),
2661 full_range: 0..15, 2579 full_range: 0..15,
2662 focus_range: Some( 2580 focus_range: 6..9,
2663 6..9,
2664 ),
2665 name: "Foo", 2581 name: "Foo",
2666 kind: TRAIT, 2582 kind: Trait,
2667 container_name: None, 2583 description: "trait Foo",
2668 description: Some(
2669 "trait Foo",
2670 ),
2671 docs: None,
2672 }, 2584 },
2673 }, 2585 },
2674 HoverGotoTypeData { 2586 HoverGotoTypeData {
@@ -2678,16 +2590,10 @@ fn main() { let s<|>t = foo(); }
2678 0, 2590 0,
2679 ), 2591 ),
2680 full_range: 16..31, 2592 full_range: 16..31,
2681 focus_range: Some( 2593 focus_range: 22..25,
2682 22..25,
2683 ),
2684 name: "Bar", 2594 name: "Bar",
2685 kind: TRAIT, 2595 kind: Trait,
2686 container_name: None, 2596 description: "trait Bar",
2687 description: Some(
2688 "trait Bar",
2689 ),
2690 docs: None,
2691 }, 2597 },
2692 }, 2598 },
2693 HoverGotoTypeData { 2599 HoverGotoTypeData {
@@ -2697,16 +2603,10 @@ fn main() { let s<|>t = foo(); }
2697 0, 2603 0,
2698 ), 2604 ),
2699 full_range: 32..44, 2605 full_range: 32..44,
2700 focus_range: Some( 2606 focus_range: 39..41,
2701 39..41,
2702 ),
2703 name: "S1", 2607 name: "S1",
2704 kind: STRUCT, 2608 kind: Struct,
2705 container_name: None, 2609 description: "struct S1",
2706 description: Some(
2707 "struct S1",
2708 ),
2709 docs: None,
2710 }, 2610 },
2711 }, 2611 },
2712 HoverGotoTypeData { 2612 HoverGotoTypeData {
@@ -2716,16 +2616,10 @@ fn main() { let s<|>t = foo(); }
2716 0, 2616 0,
2717 ), 2617 ),
2718 full_range: 45..57, 2618 full_range: 45..57,
2719 focus_range: Some( 2619 focus_range: 52..54,
2720 52..54,
2721 ),
2722 name: "S2", 2620 name: "S2",
2723 kind: STRUCT, 2621 kind: Struct,
2724 container_name: None, 2622 description: "struct S2",
2725 description: Some(
2726 "struct S2",
2727 ),
2728 docs: None,
2729 }, 2623 },
2730 }, 2624 },
2731 ], 2625 ],
@@ -2753,16 +2647,10 @@ fn foo(ar<|>g: &impl Foo) {}
2753 0, 2647 0,
2754 ), 2648 ),
2755 full_range: 0..12, 2649 full_range: 0..12,
2756 focus_range: Some( 2650 focus_range: 6..9,
2757 6..9,
2758 ),
2759 name: "Foo", 2651 name: "Foo",
2760 kind: TRAIT, 2652 kind: Trait,
2761 container_name: None, 2653 description: "trait Foo",
2762 description: Some(
2763 "trait Foo",
2764 ),
2765 docs: None,
2766 }, 2654 },
2767 }, 2655 },
2768 ], 2656 ],
@@ -2793,16 +2681,10 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2793 0, 2681 0,
2794 ), 2682 ),
2795 full_range: 0..12, 2683 full_range: 0..12,
2796 focus_range: Some( 2684 focus_range: 6..9,
2797 6..9,
2798 ),
2799 name: "Foo", 2685 name: "Foo",
2800 kind: TRAIT, 2686 kind: Trait,
2801 container_name: None, 2687 description: "trait Foo",
2802 description: Some(
2803 "trait Foo",
2804 ),
2805 docs: None,
2806 }, 2688 },
2807 }, 2689 },
2808 HoverGotoTypeData { 2690 HoverGotoTypeData {
@@ -2812,16 +2694,10 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2812 0, 2694 0,
2813 ), 2695 ),
2814 full_range: 13..28, 2696 full_range: 13..28,
2815 focus_range: Some( 2697 focus_range: 19..22,
2816 19..22,
2817 ),
2818 name: "Bar", 2698 name: "Bar",
2819 kind: TRAIT, 2699 kind: Trait,
2820 container_name: None, 2700 description: "trait Bar",
2821 description: Some(
2822 "trait Bar",
2823 ),
2824 docs: None,
2825 }, 2701 },
2826 }, 2702 },
2827 HoverGotoTypeData { 2703 HoverGotoTypeData {
@@ -2831,16 +2707,10 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2831 0, 2707 0,
2832 ), 2708 ),
2833 full_range: 29..39, 2709 full_range: 29..39,
2834 focus_range: Some( 2710 focus_range: 36..37,
2835 36..37,
2836 ),
2837 name: "S", 2711 name: "S",
2838 kind: STRUCT, 2712 kind: Struct,
2839 container_name: None, 2713 description: "struct S",
2840 description: Some(
2841 "struct S",
2842 ),
2843 docs: None,
2844 }, 2714 },
2845 }, 2715 },
2846 ], 2716 ],
@@ -2876,16 +2746,10 @@ mod future {
2876 0, 2746 0,
2877 ), 2747 ),
2878 full_range: 101..163, 2748 full_range: 101..163,
2879 focus_range: Some( 2749 focus_range: 140..146,
2880 140..146,
2881 ),
2882 name: "Future", 2750 name: "Future",
2883 kind: TRAIT, 2751 kind: Trait,
2884 container_name: None, 2752 description: "pub trait Future",
2885 description: Some(
2886 "pub trait Future",
2887 ),
2888 docs: None,
2889 }, 2753 },
2890 }, 2754 },
2891 HoverGotoTypeData { 2755 HoverGotoTypeData {
@@ -2895,16 +2759,10 @@ mod future {
2895 0, 2759 0,
2896 ), 2760 ),
2897 full_range: 0..9, 2761 full_range: 0..9,
2898 focus_range: Some( 2762 focus_range: 7..8,
2899 7..8,
2900 ),
2901 name: "S", 2763 name: "S",
2902 kind: STRUCT, 2764 kind: Struct,
2903 container_name: None, 2765 description: "struct S",
2904 description: Some(
2905 "struct S",
2906 ),
2907 docs: None,
2908 }, 2766 },
2909 }, 2767 },
2910 ], 2768 ],
@@ -2933,16 +2791,10 @@ fn foo(ar<|>g: &impl Foo<S>) {}
2933 0, 2791 0,
2934 ), 2792 ),
2935 full_range: 0..15, 2793 full_range: 0..15,
2936 focus_range: Some( 2794 focus_range: 6..9,
2937 6..9,
2938 ),
2939 name: "Foo", 2795 name: "Foo",
2940 kind: TRAIT, 2796 kind: Trait,
2941 container_name: None, 2797 description: "trait Foo",
2942 description: Some(
2943 "trait Foo",
2944 ),
2945 docs: None,
2946 }, 2798 },
2947 }, 2799 },
2948 HoverGotoTypeData { 2800 HoverGotoTypeData {
@@ -2952,16 +2804,10 @@ fn foo(ar<|>g: &impl Foo<S>) {}
2952 0, 2804 0,
2953 ), 2805 ),
2954 full_range: 16..27, 2806 full_range: 16..27,
2955 focus_range: Some( 2807 focus_range: 23..24,
2956 23..24,
2957 ),
2958 name: "S", 2808 name: "S",
2959 kind: STRUCT, 2809 kind: Struct,
2960 container_name: None, 2810 description: "struct S",
2961 description: Some(
2962 "struct S",
2963 ),
2964 docs: None,
2965 }, 2811 },
2966 }, 2812 },
2967 ], 2813 ],
@@ -2995,16 +2841,10 @@ fn main() { let s<|>t = foo(); }
2995 0, 2841 0,
2996 ), 2842 ),
2997 full_range: 42..55, 2843 full_range: 42..55,
2998 focus_range: Some( 2844 focus_range: 49..50,
2999 49..50,
3000 ),
3001 name: "B", 2845 name: "B",
3002 kind: STRUCT, 2846 kind: Struct,
3003 container_name: None, 2847 description: "struct B",
3004 description: Some(
3005 "struct B",
3006 ),
3007 docs: None,
3008 }, 2848 },
3009 }, 2849 },
3010 HoverGotoTypeData { 2850 HoverGotoTypeData {
@@ -3014,16 +2854,10 @@ fn main() { let s<|>t = foo(); }
3014 0, 2854 0,
3015 ), 2855 ),
3016 full_range: 0..12, 2856 full_range: 0..12,
3017 focus_range: Some( 2857 focus_range: 6..9,
3018 6..9,
3019 ),
3020 name: "Foo", 2858 name: "Foo",
3021 kind: TRAIT, 2859 kind: Trait,
3022 container_name: None, 2860 description: "trait Foo",
3023 description: Some(
3024 "trait Foo",
3025 ),
3026 docs: None,
3027 }, 2861 },
3028 }, 2862 },
3029 ], 2863 ],
@@ -3051,16 +2885,10 @@ fn foo(ar<|>g: &dyn Foo) {}
3051 0, 2885 0,
3052 ), 2886 ),
3053 full_range: 0..12, 2887 full_range: 0..12,
3054 focus_range: Some( 2888 focus_range: 6..9,
3055 6..9,
3056 ),
3057 name: "Foo", 2889 name: "Foo",
3058 kind: TRAIT, 2890 kind: Trait,
3059 container_name: None, 2891 description: "trait Foo",
3060 description: Some(
3061 "trait Foo",
3062 ),
3063 docs: None,
3064 }, 2892 },
3065 }, 2893 },
3066 ], 2894 ],
@@ -3089,16 +2917,10 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
3089 0, 2917 0,
3090 ), 2918 ),
3091 full_range: 0..15, 2919 full_range: 0..15,
3092 focus_range: Some( 2920 focus_range: 6..9,
3093 6..9,
3094 ),
3095 name: "Foo", 2921 name: "Foo",
3096 kind: TRAIT, 2922 kind: Trait,
3097 container_name: None, 2923 description: "trait Foo",
3098 description: Some(
3099 "trait Foo",
3100 ),
3101 docs: None,
3102 }, 2924 },
3103 }, 2925 },
3104 HoverGotoTypeData { 2926 HoverGotoTypeData {
@@ -3108,16 +2930,10 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
3108 0, 2930 0,
3109 ), 2931 ),
3110 full_range: 16..27, 2932 full_range: 16..27,
3111 focus_range: Some( 2933 focus_range: 23..24,
3112 23..24,
3113 ),
3114 name: "S", 2934 name: "S",
3115 kind: STRUCT, 2935 kind: Struct,
3116 container_name: None, 2936 description: "struct S",
3117 description: Some(
3118 "struct S",
3119 ),
3120 docs: None,
3121 }, 2937 },
3122 }, 2938 },
3123 ], 2939 ],
@@ -3149,16 +2965,10 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3149 0, 2965 0,
3150 ), 2966 ),
3151 full_range: 0..21, 2967 full_range: 0..21,
3152 focus_range: Some( 2968 focus_range: 6..15,
3153 6..15,
3154 ),
3155 name: "ImplTrait", 2969 name: "ImplTrait",
3156 kind: TRAIT, 2970 kind: Trait,
3157 container_name: None, 2971 description: "trait ImplTrait",
3158 description: Some(
3159 "trait ImplTrait",
3160 ),
3161 docs: None,
3162 }, 2972 },
3163 }, 2973 },
3164 HoverGotoTypeData { 2974 HoverGotoTypeData {
@@ -3168,16 +2978,10 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3168 0, 2978 0,
3169 ), 2979 ),
3170 full_range: 43..57, 2980 full_range: 43..57,
3171 focus_range: Some( 2981 focus_range: 50..51,
3172 50..51,
3173 ),
3174 name: "B", 2982 name: "B",
3175 kind: STRUCT, 2983 kind: Struct,
3176 container_name: None, 2984 description: "struct B",
3177 description: Some(
3178 "struct B",
3179 ),
3180 docs: None,
3181 }, 2985 },
3182 }, 2986 },
3183 HoverGotoTypeData { 2987 HoverGotoTypeData {
@@ -3187,16 +2991,10 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3187 0, 2991 0,
3188 ), 2992 ),
3189 full_range: 22..42, 2993 full_range: 22..42,
3190 focus_range: Some( 2994 focus_range: 28..36,
3191 28..36,
3192 ),
3193 name: "DynTrait", 2995 name: "DynTrait",
3194 kind: TRAIT, 2996 kind: Trait,
3195 container_name: None, 2997 description: "trait DynTrait",
3196 description: Some(
3197 "trait DynTrait",
3198 ),
3199 docs: None,
3200 }, 2998 },
3201 }, 2999 },
3202 HoverGotoTypeData { 3000 HoverGotoTypeData {
@@ -3206,16 +3004,10 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3206 0, 3004 0,
3207 ), 3005 ),
3208 full_range: 58..69, 3006 full_range: 58..69,
3209 focus_range: Some( 3007 focus_range: 65..66,
3210 65..66,
3211 ),
3212 name: "S", 3008 name: "S",
3213 kind: STRUCT, 3009 kind: Struct,
3214 container_name: None, 3010 description: "struct S",
3215 description: Some(
3216 "struct S",
3217 ),
3218 docs: None,
3219 }, 3011 },
3220 }, 3012 },
3221 ], 3013 ],
@@ -3254,16 +3046,10 @@ fn main() { let s<|>t = test().get(); }
3254 0, 3046 0,
3255 ), 3047 ),
3256 full_range: 0..62, 3048 full_range: 0..62,
3257 focus_range: Some( 3049 focus_range: 6..9,
3258 6..9,
3259 ),
3260 name: "Foo", 3050 name: "Foo",
3261 kind: TRAIT, 3051 kind: Trait,
3262 container_name: None, 3052 description: "trait Foo",
3263 description: Some(
3264 "trait Foo",
3265 ),
3266 docs: None,
3267 }, 3053 },
3268 }, 3054 },
3269 ], 3055 ],
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index c5c652cda..dbad9a84f 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -57,14 +57,14 @@ use ide_db::{
57 symbol_index::{self, FileSymbol}, 57 symbol_index::{self, FileSymbol},
58 LineIndexDatabase, 58 LineIndexDatabase,
59}; 59};
60use syntax::{SourceFile, TextRange, TextSize}; 60use syntax::SourceFile;
61 61
62use crate::display::ToNav; 62use crate::display::ToNav;
63 63
64pub use crate::{ 64pub use crate::{
65 call_hierarchy::CallItem, 65 call_hierarchy::CallItem,
66 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity}, 66 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
67 display::NavigationTarget, 67 display::navigation_target::{NavigationTarget, SymbolKind},
68 expand_macro::ExpandedMacro, 68 expand_macro::ExpandedMacro,
69 file_structure::StructureNode, 69 file_structure::StructureNode,
70 folding_ranges::{Fold, FoldKind}, 70 folding_ranges::{Fold, FoldKind},
@@ -79,22 +79,21 @@ pub use crate::{
79 HighlightedRange, 79 HighlightedRange,
80 }, 80 },
81}; 81};
82pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
82pub use completion::{ 83pub use completion::{
83 CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability, 84 CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability,
84 CompletionScore, ImportEdit, InsertTextFormat, 85 CompletionScore, ImportEdit, InsertTextFormat,
85}; 86};
86pub use ide_db::{
87 call_info::CallInfo,
88 search::{Reference, ReferenceAccess, ReferenceKind},
89};
90
91pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
92pub use hir::{Documentation, Semantics}; 87pub use hir::{Documentation, Semantics};
93pub use ide_db::base_db::{ 88pub use ide_db::base_db::{
94 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, 89 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
95 SourceRootId, 90 SourceRootId,
96}; 91};
97pub use ide_db::{ 92pub use ide_db::{
93 call_info::CallInfo,
94 search::{Reference, ReferenceAccess, ReferenceKind},
95};
96pub use ide_db::{
98 label::Label, 97 label::Label,
99 line_index::{LineCol, LineIndex}, 98 line_index::{LineCol, LineIndex},
100 search::SearchScope, 99 search::SearchScope,
@@ -103,6 +102,7 @@ pub use ide_db::{
103 RootDatabase, 102 RootDatabase,
104}; 103};
105pub use ssr::SsrError; 104pub use ssr::SsrError;
105pub use syntax::{TextRange, TextSize};
106pub use text_edit::{Indel, TextEdit}; 106pub use text_edit::{Indel, TextEdit};
107 107
108pub type Cancelable<T> = Result<T, Canceled>; 108pub type Cancelable<T> = Result<T, Canceled>;
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index 6cc3b2991..be344a09b 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -78,7 +78,7 @@ mod tests {
78 ", 78 ",
79 ); 79 );
80 let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); 80 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
81 nav.assert_match("foo MODULE FileId(0) 0..8"); 81 nav.assert_match("foo Module FileId(0) 0..8");
82 } 82 }
83 83
84 #[test] 84 #[test]
@@ -97,7 +97,7 @@ mod tests {
97 ", 97 ",
98 ); 98 );
99 let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); 99 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
100 nav.assert_match("foo MODULE FileId(0) 0..8"); 100 nav.assert_match("foo Module FileId(0) 0..8");
101 } 101 }
102 102
103 #[test] 103 #[test]
@@ -113,7 +113,7 @@ mod tests {
113 ", 113 ",
114 ); 114 );
115 let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); 115 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
116 nav.assert_match("baz MODULE FileId(0) 32..44"); 116 nav.assert_match("baz Module FileId(0) 32..44");
117 } 117 }
118 118
119 #[test] 119 #[test]
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 98190a86b..18ea19305 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -24,7 +24,7 @@ use syntax::{
24 match_ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TokenAtOffset, 24 match_ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TokenAtOffset,
25}; 25};
26 26
27use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; 27use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind};
28 28
29#[derive(Debug, Clone)] 29#[derive(Debug, Clone)]
30pub struct ReferenceSearchResult { 30pub struct ReferenceSearchResult {
@@ -278,7 +278,7 @@ fn try_find_self_references(
278 full_range: self_param.syntax().text_range(), 278 full_range: self_param.syntax().text_range(),
279 focus_range: Some(param_self_token.text_range()), 279 focus_range: Some(param_self_token.text_range()),
280 name: param_self_token.text().clone(), 280 name: param_self_token.text().clone(),
281 kind: param_self_token.kind(), 281 kind: Some(SymbolKind::SelfParam),
282 container_name: None, 282 container_name: None,
283 description: None, 283 description: None,
284 docs: None, 284 docs: None,
@@ -343,7 +343,7 @@ fn main() {
343} 343}
344"#, 344"#,
345 expect![[r#" 345 expect![[r#"
346 Foo STRUCT FileId(0) 0..26 7..10 Other 346 Foo Struct FileId(0) 0..26 7..10 Other
347 347
348 FileId(0) 101..104 StructLiteral 348 FileId(0) 101..104 StructLiteral
349 "#]], 349 "#]],
@@ -361,7 +361,7 @@ struct Foo<|> {}
361} 361}
362"#, 362"#,
363 expect![[r#" 363 expect![[r#"
364 Foo STRUCT FileId(0) 0..13 7..10 Other 364 Foo Struct FileId(0) 0..13 7..10 Other
365 365
366 FileId(0) 41..44 Other 366 FileId(0) 41..44 Other
367 FileId(0) 54..57 StructLiteral 367 FileId(0) 54..57 StructLiteral
@@ -380,7 +380,7 @@ struct Foo<T> <|>{}
380} 380}
381"#, 381"#,
382 expect![[r#" 382 expect![[r#"
383 Foo STRUCT FileId(0) 0..16 7..10 Other 383 Foo Struct FileId(0) 0..16 7..10 Other
384 384
385 FileId(0) 64..67 StructLiteral 385 FileId(0) 64..67 StructLiteral
386 "#]], 386 "#]],
@@ -399,7 +399,7 @@ fn main() {
399} 399}
400"#, 400"#,
401 expect![[r#" 401 expect![[r#"
402 Foo STRUCT FileId(0) 0..16 7..10 Other 402 Foo Struct FileId(0) 0..16 7..10 Other
403 403
404 FileId(0) 54..57 StructLiteral 404 FileId(0) 54..57 StructLiteral
405 "#]], 405 "#]],
@@ -420,7 +420,7 @@ fn main() {
420} 420}
421"#, 421"#,
422 expect![[r#" 422 expect![[r#"
423 Foo ENUM FileId(0) 0..26 5..8 Other 423 Foo Enum FileId(0) 0..26 5..8 Other
424 424
425 FileId(0) 63..66 EnumLiteral 425 FileId(0) 63..66 EnumLiteral
426 "#]], 426 "#]],
@@ -441,7 +441,7 @@ fn main() {
441} 441}
442"#, 442"#,
443 expect![[r#" 443 expect![[r#"
444 Foo ENUM FileId(0) 0..26 5..8 Other 444 Foo Enum FileId(0) 0..26 5..8 Other
445 445
446 FileId(0) 50..53 Other 446 FileId(0) 50..53 Other
447 FileId(0) 63..66 EnumLiteral 447 FileId(0) 63..66 EnumLiteral
@@ -463,7 +463,7 @@ fn main() {
463} 463}
464"#, 464"#,
465 expect![[r#" 465 expect![[r#"
466 Foo ENUM FileId(0) 0..32 5..8 Other 466 Foo Enum FileId(0) 0..32 5..8 Other
467 467
468 FileId(0) 73..76 EnumLiteral 468 FileId(0) 73..76 EnumLiteral
469 "#]], 469 "#]],
@@ -484,7 +484,7 @@ fn main() {
484} 484}
485"#, 485"#,
486 expect![[r#" 486 expect![[r#"
487 Foo ENUM FileId(0) 0..33 5..8 Other 487 Foo Enum FileId(0) 0..33 5..8 Other
488 488
489 FileId(0) 70..73 EnumLiteral 489 FileId(0) 70..73 EnumLiteral
490 "#]], 490 "#]],
@@ -507,7 +507,7 @@ fn main() {
507 i = 5; 507 i = 5;
508}"#, 508}"#,
509 expect![[r#" 509 expect![[r#"
510 i IDENT_PAT FileId(0) 24..25 Other Write 510 i Local FileId(0) 24..25 Other Write
511 511
512 FileId(0) 50..51 Other Write 512 FileId(0) 50..51 Other Write
513 FileId(0) 54..55 Other Read 513 FileId(0) 54..55 Other Read
@@ -531,7 +531,7 @@ fn bar() {
531} 531}
532"#, 532"#,
533 expect![[r#" 533 expect![[r#"
534 spam IDENT_PAT FileId(0) 19..23 Other 534 spam Local FileId(0) 19..23 Other
535 535
536 FileId(0) 34..38 Other Read 536 FileId(0) 34..38 Other Read
537 FileId(0) 41..45 Other Read 537 FileId(0) 41..45 Other Read
@@ -546,7 +546,7 @@ fn bar() {
546fn foo(i : u32) -> u32 { i<|> } 546fn foo(i : u32) -> u32 { i<|> }
547"#, 547"#,
548 expect![[r#" 548 expect![[r#"
549 i IDENT_PAT FileId(0) 7..8 Other 549 i ValueParam FileId(0) 7..8 Other
550 550
551 FileId(0) 25..26 Other Read 551 FileId(0) 25..26 Other Read
552 "#]], 552 "#]],
@@ -560,7 +560,7 @@ fn foo(i : u32) -> u32 { i<|> }
560fn foo(i<|> : u32) -> u32 { i } 560fn foo(i<|> : u32) -> u32 { i }
561"#, 561"#,
562 expect![[r#" 562 expect![[r#"
563 i IDENT_PAT FileId(0) 7..8 Other 563 i ValueParam FileId(0) 7..8 Other
564 564
565 FileId(0) 25..26 Other Read 565 FileId(0) 25..26 Other Read
566 "#]], 566 "#]],
@@ -581,7 +581,7 @@ fn main(s: Foo) {
581} 581}
582"#, 582"#,
583 expect![[r#" 583 expect![[r#"
584 spam RECORD_FIELD FileId(0) 17..30 21..25 Other 584 spam Field FileId(0) 17..30 21..25 Other
585 585
586 FileId(0) 67..71 Other Read 586 FileId(0) 67..71 Other Read
587 "#]], 587 "#]],
@@ -598,7 +598,7 @@ impl Foo {
598} 598}
599"#, 599"#,
600 expect![[r#" 600 expect![[r#"
601 f FN FileId(0) 27..43 30..31 Other 601 f Function FileId(0) 27..43 30..31 Other
602 602
603 "#]], 603 "#]],
604 ); 604 );
@@ -615,7 +615,7 @@ enum Foo {
615} 615}
616"#, 616"#,
617 expect![[r#" 617 expect![[r#"
618 B VARIANT FileId(0) 22..23 22..23 Other 618 B Variant FileId(0) 22..23 22..23 Other
619 619
620 "#]], 620 "#]],
621 ); 621 );
@@ -632,7 +632,7 @@ enum Foo {
632} 632}
633"#, 633"#,
634 expect![[r#" 634 expect![[r#"
635 field RECORD_FIELD FileId(0) 26..35 26..31 Other 635 field Field FileId(0) 26..35 26..31 Other
636 636
637 "#]], 637 "#]],
638 ); 638 );
@@ -673,7 +673,7 @@ fn f() {
673} 673}
674"#, 674"#,
675 expect![[r#" 675 expect![[r#"
676 Foo STRUCT FileId(1) 17..51 28..31 Other 676 Foo Struct FileId(1) 17..51 28..31 Other
677 677
678 FileId(0) 53..56 StructLiteral 678 FileId(0) 53..56 StructLiteral
679 FileId(2) 79..82 StructLiteral 679 FileId(2) 79..82 StructLiteral
@@ -703,7 +703,7 @@ pub struct Foo {
703} 703}
704"#, 704"#,
705 expect![[r#" 705 expect![[r#"
706 foo SOURCE_FILE FileId(1) 0..35 Other 706 foo Module FileId(1) 0..35 Other
707 707
708 FileId(0) 14..17 Other 708 FileId(0) 14..17 Other
709 "#]], 709 "#]],
@@ -731,7 +731,7 @@ pub(super) struct Foo<|> {
731} 731}
732"#, 732"#,
733 expect![[r#" 733 expect![[r#"
734 Foo STRUCT FileId(2) 0..41 18..21 Other 734 Foo Struct FileId(2) 0..41 18..21 Other
735 735
736 FileId(1) 20..23 Other 736 FileId(1) 20..23 Other
737 FileId(1) 47..50 StructLiteral 737 FileId(1) 47..50 StructLiteral
@@ -759,7 +759,7 @@ pub(super) struct Foo<|> {
759 code, 759 code,
760 None, 760 None,
761 expect![[r#" 761 expect![[r#"
762 quux FN FileId(0) 19..35 26..30 Other 762 quux Function FileId(0) 19..35 26..30 Other
763 763
764 FileId(1) 16..20 StructLiteral 764 FileId(1) 16..20 StructLiteral
765 FileId(2) 16..20 StructLiteral 765 FileId(2) 16..20 StructLiteral
@@ -770,7 +770,7 @@ pub(super) struct Foo<|> {
770 code, 770 code,
771 Some(SearchScope::single_file(FileId(2))), 771 Some(SearchScope::single_file(FileId(2))),
772 expect![[r#" 772 expect![[r#"
773 quux FN FileId(0) 19..35 26..30 Other 773 quux Function FileId(0) 19..35 26..30 Other
774 774
775 FileId(2) 16..20 StructLiteral 775 FileId(2) 16..20 StructLiteral
776 "#]], 776 "#]],
@@ -790,7 +790,7 @@ fn foo() {
790} 790}
791"#, 791"#,
792 expect![[r#" 792 expect![[r#"
793 m1 MACRO_RULES FileId(0) 0..46 29..31 Other 793 m1 Macro FileId(0) 0..46 29..31 Other
794 794
795 FileId(0) 63..65 StructLiteral 795 FileId(0) 63..65 StructLiteral
796 FileId(0) 73..75 StructLiteral 796 FileId(0) 73..75 StructLiteral
@@ -808,7 +808,7 @@ fn foo() {
808} 808}
809"#, 809"#,
810 expect![[r#" 810 expect![[r#"
811 i IDENT_PAT FileId(0) 23..24 Other Write 811 i Local FileId(0) 23..24 Other Write
812 812
813 FileId(0) 34..35 Other Write 813 FileId(0) 34..35 Other Write
814 FileId(0) 38..39 Other Read 814 FileId(0) 38..39 Other Read
@@ -830,7 +830,7 @@ fn foo() {
830} 830}
831"#, 831"#,
832 expect![[r#" 832 expect![[r#"
833 f RECORD_FIELD FileId(0) 15..21 15..16 Other 833 f Field FileId(0) 15..21 15..16 Other
834 834
835 FileId(0) 55..56 RecordFieldExprOrPat Read 835 FileId(0) 55..56 RecordFieldExprOrPat Read
836 FileId(0) 68..69 Other Write 836 FileId(0) 68..69 Other Write
@@ -848,7 +848,7 @@ fn foo() {
848} 848}
849"#, 849"#,
850 expect![[r#" 850 expect![[r#"
851 i IDENT_PAT FileId(0) 19..20 Other 851 i Local FileId(0) 19..20 Other
852 852
853 FileId(0) 26..27 Other Write 853 FileId(0) 26..27 Other Write
854 "#]], 854 "#]],
@@ -872,7 +872,7 @@ fn main() {
872} 872}
873"#, 873"#,
874 expect![[r#" 874 expect![[r#"
875 new FN FileId(0) 54..81 61..64 Other 875 new Function FileId(0) 54..81 61..64 Other
876 876
877 FileId(0) 126..129 StructLiteral 877 FileId(0) 126..129 StructLiteral
878 "#]], 878 "#]],
@@ -894,7 +894,7 @@ use crate::f;
894fn g() { f(); } 894fn g() { f(); }
895"#, 895"#,
896 expect![[r#" 896 expect![[r#"
897 f FN FileId(0) 22..31 25..26 Other 897 f Function FileId(0) 22..31 25..26 Other
898 898
899 FileId(1) 11..12 Other 899 FileId(1) 11..12 Other
900 FileId(1) 24..25 StructLiteral 900 FileId(1) 24..25 StructLiteral
@@ -917,7 +917,7 @@ fn f(s: S) {
917} 917}
918"#, 918"#,
919 expect![[r#" 919 expect![[r#"
920 field RECORD_FIELD FileId(0) 15..24 15..20 Other 920 field Field FileId(0) 15..24 15..20 Other
921 921
922 FileId(0) 68..73 FieldShorthandForField Read 922 FileId(0) 68..73 FieldShorthandForField Read
923 "#]], 923 "#]],
@@ -941,7 +941,7 @@ fn f(e: En) {
941} 941}
942"#, 942"#,
943 expect![[r#" 943 expect![[r#"
944 field RECORD_FIELD FileId(0) 32..41 32..37 Other 944 field Field FileId(0) 32..41 32..37 Other
945 945
946 FileId(0) 102..107 FieldShorthandForField Read 946 FileId(0) 102..107 FieldShorthandForField Read
947 "#]], 947 "#]],
@@ -965,7 +965,7 @@ fn f() -> m::En {
965} 965}
966"#, 966"#,
967 expect![[r#" 967 expect![[r#"
968 field RECORD_FIELD FileId(0) 56..65 56..61 Other 968 field Field FileId(0) 56..65 56..61 Other
969 969
970 FileId(0) 125..130 RecordFieldExprOrPat Read 970 FileId(0) 125..130 RecordFieldExprOrPat Read
971 "#]], 971 "#]],
@@ -990,7 +990,7 @@ impl Foo {
990} 990}
991"#, 991"#,
992 expect![[r#" 992 expect![[r#"
993 self SELF_KW FileId(0) 47..51 47..51 SelfKw Read 993 self SelfParam FileId(0) 47..51 47..51 SelfKw Read
994 994
995 FileId(0) 71..75 SelfKw Read 995 FileId(0) 71..75 SelfKw Read
996 FileId(0) 152..156 SelfKw Read 996 FileId(0) 152..156 SelfKw Read
@@ -1038,7 +1038,7 @@ fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> {
1038} 1038}
1039"#, 1039"#,
1040 expect![[r#" 1040 expect![[r#"
1041 'a LIFETIME_PARAM FileId(0) 55..57 55..57 Lifetime 1041 'a LifetimeParam FileId(0) 55..57 55..57 Lifetime
1042 1042
1043 FileId(0) 63..65 Lifetime 1043 FileId(0) 63..65 Lifetime
1044 FileId(0) 71..73 Lifetime 1044 FileId(0) 71..73 Lifetime
@@ -1056,7 +1056,7 @@ fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> {
1056type Foo<'a, T> where T: 'a<|> = &'a T; 1056type Foo<'a, T> where T: 'a<|> = &'a T;
1057"#, 1057"#,
1058 expect![[r#" 1058 expect![[r#"
1059 'a LIFETIME_PARAM FileId(0) 9..11 9..11 Lifetime 1059 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime
1060 1060
1061 FileId(0) 25..27 Lifetime 1061 FileId(0) 25..27 Lifetime
1062 FileId(0) 31..33 Lifetime 1062 FileId(0) 31..33 Lifetime
@@ -1078,7 +1078,7 @@ impl<'a> Foo<'a> for &'a () {
1078} 1078}
1079"#, 1079"#,
1080 expect![[r#" 1080 expect![[r#"
1081 'a LIFETIME_PARAM FileId(0) 47..49 47..49 Lifetime 1081 'a LifetimeParam FileId(0) 47..49 47..49 Lifetime
1082 1082
1083 FileId(0) 55..57 Lifetime 1083 FileId(0) 55..57 Lifetime
1084 FileId(0) 64..66 Lifetime 1084 FileId(0) 64..66 Lifetime
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 56e923841..cd721b7eb 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -1488,4 +1488,39 @@ impl<'yeeee> Foo<'yeeee> for &'yeeee () {
1488"#, 1488"#,
1489 ) 1489 )
1490 } 1490 }
1491
1492 #[test]
1493 fn test_rename_bind_pat() {
1494 check(
1495 "new_name",
1496 r#"
1497fn main() {
1498 enum CustomOption<T> {
1499 None,
1500 Some(T),
1501 }
1502
1503 let test_variable = CustomOption::Some(22);
1504
1505 match test_variable {
1506 CustomOption::Some(foo<|>) if foo == 11 => {}
1507 _ => (),
1508 }
1509}"#,
1510 r#"
1511fn main() {
1512 enum CustomOption<T> {
1513 None,
1514 Some(T),
1515 }
1516
1517 let test_variable = CustomOption::Some(22);
1518
1519 match test_variable {
1520 CustomOption::Some(new_name) if new_name == 11 => {}
1521 _ => (),
1522 }
1523}"#,
1524 );
1525 }
1491} 1526}
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 96462a7b0..2f2b99130 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -2,7 +2,7 @@ use std::fmt;
2 2
3use assists::utils::test_related_attribute; 3use assists::utils::test_related_attribute;
4use cfg::CfgExpr; 4use cfg::CfgExpr;
5use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics}; 5use hir::{AsAssocItem, HasAttrs, InFile, Semantics};
6use ide_db::RootDatabase; 6use ide_db::RootDatabase;
7use itertools::Itertools; 7use itertools::Itertools;
8use syntax::{ 8use syntax::{
@@ -10,7 +10,10 @@ use syntax::{
10 match_ast, SyntaxNode, 10 match_ast, SyntaxNode,
11}; 11};
12 12
13use crate::{display::ToNav, FileId, NavigationTarget}; 13use crate::{
14 display::{ToNav, TryToNav},
15 FileId, NavigationTarget, SymbolKind,
16};
14 17
15#[derive(Debug, Clone)] 18#[derive(Debug, Clone)]
16pub struct Runnable { 19pub struct Runnable {
@@ -101,124 +104,113 @@ pub(crate) fn runnable(
101 item: SyntaxNode, 104 item: SyntaxNode,
102 file_id: FileId, 105 file_id: FileId,
103) -> Option<Runnable> { 106) -> Option<Runnable> {
104 match_ast! { 107 let runnable_item = match_ast! {
105 match item { 108 match (item.clone()) {
106 ast::Struct(it) => runnable_struct(sema, it, file_id),
107 ast::Fn(it) => runnable_fn(sema, it, file_id), 109 ast::Fn(it) => runnable_fn(sema, it, file_id),
108 ast::Module(it) => runnable_mod(sema, it, file_id), 110 ast::Module(it) => runnable_mod(sema, it),
109 _ => None, 111 _ => None,
110 } 112 }
111 } 113 };
114 runnable_item.or_else(|| runnable_doctest(sema, item))
112} 115}
113 116
114fn runnable_fn( 117fn runnable_fn(sema: &Semantics<RootDatabase>, func: ast::Fn, file_id: FileId) -> Option<Runnable> {
115 sema: &Semantics<RootDatabase>, 118 let def = sema.to_def(&func)?;
116 fn_def: ast::Fn, 119 let name_string = func.name()?.text().to_string();
117 file_id: FileId,
118) -> Option<Runnable> {
119 let name_string = fn_def.name()?.text().to_string();
120 120
121 let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &fn_def));
122 let kind = if name_string == "main" { 121 let kind = if name_string == "main" {
123 RunnableKind::Bin 122 RunnableKind::Bin
124 } else { 123 } else {
125 let test_id = match sema.to_def(&fn_def).map(|def| def.module(sema.db)) { 124 let canonical_path = sema.to_def(&func).and_then(|def| {
126 Some(module) => { 125 let def: hir::ModuleDef = def.into();
127 let def = sema.to_def(&fn_def)?; 126 def.canonical_path(sema.db)
128 let impl_trait_name = def.as_assoc_item(sema.db).and_then(|assoc_item| { 127 });
129 match assoc_item.container(sema.db) { 128 let test_id = canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name_string));
130 hir::AssocItemContainer::Trait(trait_item) => { 129
131 Some(trait_item.name(sema.db).to_string()) 130 if test_related_attribute(&func).is_some() {
132 } 131 let attr = TestAttr::from_fn(&func);
133 hir::AssocItemContainer::Impl(impl_def) => impl_def
134 .target_ty(sema.db)
135 .as_adt()
136 .map(|adt| adt.name(sema.db).to_string()),
137 }
138 });
139
140 let path_iter = module
141 .path_to_root(sema.db)
142 .into_iter()
143 .rev()
144 .filter_map(|it| it.name(sema.db))
145 .map(|name| name.to_string());
146
147 let path = if let Some(impl_trait_name) = impl_trait_name {
148 path_iter
149 .chain(std::iter::once(impl_trait_name))
150 .chain(std::iter::once(name_string))
151 .join("::")
152 } else {
153 path_iter.chain(std::iter::once(name_string)).join("::")
154 };
155
156 TestId::Path(path)
157 }
158 None => TestId::Name(name_string),
159 };
160
161 if test_related_attribute(&fn_def).is_some() {
162 let attr = TestAttr::from_fn(&fn_def);
163 RunnableKind::Test { test_id, attr } 132 RunnableKind::Test { test_id, attr }
164 } else if fn_def.has_atom_attr("bench") { 133 } else if func.has_atom_attr("bench") {
165 RunnableKind::Bench { test_id } 134 RunnableKind::Bench { test_id }
166 } else if has_runnable_doc_test(&attrs) {
167 RunnableKind::DocTest { test_id }
168 } else { 135 } else {
169 return None; 136 return None;
170 } 137 }
171 }; 138 };
172 139
173 let cfg = attrs.cfg(); 140 let nav = NavigationTarget::from_named(
174 141 sema.db,
175 let nav = if let RunnableKind::DocTest { .. } = kind { 142 InFile::new(file_id.into(), &func),
176 NavigationTarget::from_doc_commented( 143 SymbolKind::Function,
177 sema.db, 144 );
178 InFile::new(file_id.into(), &fn_def), 145 let cfg = def.attrs(sema.db).cfg();
179 InFile::new(file_id.into(), &fn_def),
180 )
181 } else {
182 NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def))
183 };
184 Some(Runnable { nav, kind, cfg }) 146 Some(Runnable { nav, kind, cfg })
185} 147}
186 148
187fn runnable_struct( 149fn runnable_doctest(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> {
188 sema: &Semantics<RootDatabase>, 150 match_ast! {
189 struct_def: ast::Struct, 151 match item {
190 file_id: FileId, 152 ast::Fn(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
191) -> Option<Runnable> { 153 ast::Struct(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
192 let name_string = struct_def.name()?.text().to_string(); 154 ast::Enum(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
155 ast::Union(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
156 ast::Trait(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
157 ast::Const(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
158 ast::Static(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
159 ast::TypeAlias(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
160 _ => None,
161 }
162 }
163}
193 164
194 let attrs = 165fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> {
195 Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &struct_def)); 166 let attrs = match def {
167 hir::ModuleDef::Module(it) => it.attrs(sema.db),
168 hir::ModuleDef::Function(it) => it.attrs(sema.db),
169 hir::ModuleDef::Adt(it) => it.attrs(sema.db),
170 hir::ModuleDef::Variant(it) => it.attrs(sema.db),
171 hir::ModuleDef::Const(it) => it.attrs(sema.db),
172 hir::ModuleDef::Static(it) => it.attrs(sema.db),
173 hir::ModuleDef::Trait(it) => it.attrs(sema.db),
174 hir::ModuleDef::TypeAlias(it) => it.attrs(sema.db),
175 hir::ModuleDef::BuiltinType(_) => return None,
176 };
196 if !has_runnable_doc_test(&attrs) { 177 if !has_runnable_doc_test(&attrs) {
197 return None; 178 return None;
198 } 179 }
199 let cfg = attrs.cfg(); 180 let def_name = def.name(sema.db).map(|it| it.to_string());
200 181 let test_id = def
201 let test_id = match sema.to_def(&struct_def).map(|def| def.module(sema.db)) { 182 .canonical_path(sema.db)
202 Some(module) => { 183 // This probably belongs to canonical path?
203 let path_iter = module 184 .map(|path| {
204 .path_to_root(sema.db) 185 let assoc_def = match def {
205 .into_iter() 186 hir::ModuleDef::Function(it) => it.as_assoc_item(sema.db),
206 .rev() 187 hir::ModuleDef::Const(it) => it.as_assoc_item(sema.db),
207 .filter_map(|it| it.name(sema.db)) 188 hir::ModuleDef::TypeAlias(it) => it.as_assoc_item(sema.db),
208 .map(|name| name.to_string()); 189 _ => None,
209 let path = path_iter.chain(std::iter::once(name_string)).join("::"); 190 };
210 191 // FIXME: this also looks very wrong
211 TestId::Path(path) 192 if let Some(assoc_def) = assoc_def {
212 } 193 if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) {
213 None => TestId::Name(name_string), 194 if let Some(adt) = imp.target_ty(sema.db).as_adt() {
214 }; 195 let name = adt.name(sema.db).to_string();
215 196 let idx = path.rfind(':').unwrap_or(0);
216 let nav = NavigationTarget::from_doc_commented( 197 let (prefix, suffix) = path.split_at(idx);
217 sema.db, 198 return format!("{}{}::{}", prefix, name, suffix);
218 InFile::new(file_id.into(), &struct_def), 199 }
219 InFile::new(file_id.into(), &struct_def), 200 }
220 ); 201 }
221 Some(Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg }) 202 path
203 })
204 .map(TestId::Path)
205 .or_else(|| def_name.clone().map(TestId::Name))?;
206
207 let mut nav = def.try_to_nav(sema.db)?;
208 nav.focus_range = None;
209 nav.description = None;
210 nav.docs = None;
211 nav.kind = None;
212 let res = Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg: attrs.cfg() };
213 Some(res)
222} 214}
223 215
224#[derive(Debug, Copy, Clone)] 216#[derive(Debug, Copy, Clone)]
@@ -262,11 +254,7 @@ fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
262 }) 254 })
263} 255}
264 256
265fn runnable_mod( 257fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
266 sema: &Semantics<RootDatabase>,
267 module: ast::Module,
268 file_id: FileId,
269) -> Option<Runnable> {
270 if !has_test_function_or_multiple_test_submodules(&module) { 258 if !has_test_function_or_multiple_test_submodules(&module) {
271 return None; 259 return None;
272 } 260 }
@@ -279,7 +267,8 @@ fn runnable_mod(
279 .filter_map(|it| it.name(sema.db)) 267 .filter_map(|it| it.name(sema.db))
280 .join("::"); 268 .join("::");
281 269
282 let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &module)); 270 let def = sema.to_def(&module)?;
271 let attrs = def.attrs(sema.db);
283 let cfg = attrs.cfg(); 272 let cfg = attrs.cfg();
284 let nav = module_def.to_nav(sema.db); 273 let nav = module_def.to_nav(sema.db);
285 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg }) 274 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg })
@@ -319,7 +308,7 @@ mod tests {
319 308
320 use crate::fixture; 309 use crate::fixture;
321 310
322 use super::{RunnableAction, BENCH, BIN, DOCTEST, TEST}; 311 use super::*;
323 312
324 fn check( 313 fn check(
325 ra_fixture: &str, 314 ra_fixture: &str,
@@ -363,14 +352,9 @@ fn bench() {}
363 0, 352 0,
364 ), 353 ),
365 full_range: 1..13, 354 full_range: 1..13,
366 focus_range: Some( 355 focus_range: 4..8,
367 4..8,
368 ),
369 name: "main", 356 name: "main",
370 kind: FN, 357 kind: Function,
371 container_name: None,
372 description: None,
373 docs: None,
374 }, 358 },
375 kind: Bin, 359 kind: Bin,
376 cfg: None, 360 cfg: None,
@@ -381,14 +365,9 @@ fn bench() {}
381 0, 365 0,
382 ), 366 ),
383 full_range: 15..39, 367 full_range: 15..39,
384 focus_range: Some( 368 focus_range: 26..34,
385 26..34,
386 ),
387 name: "test_foo", 369 name: "test_foo",
388 kind: FN, 370 kind: Function,
389 container_name: None,
390 description: None,
391 docs: None,
392 }, 371 },
393 kind: Test { 372 kind: Test {
394 test_id: Path( 373 test_id: Path(
@@ -406,14 +385,9 @@ fn bench() {}
406 0, 385 0,
407 ), 386 ),
408 full_range: 41..75, 387 full_range: 41..75,
409 focus_range: Some( 388 focus_range: 62..70,
410 62..70,
411 ),
412 name: "test_foo", 389 name: "test_foo",
413 kind: FN, 390 kind: Function,
414 container_name: None,
415 description: None,
416 docs: None,
417 }, 391 },
418 kind: Test { 392 kind: Test {
419 test_id: Path( 393 test_id: Path(
@@ -431,14 +405,9 @@ fn bench() {}
431 0, 405 0,
432 ), 406 ),
433 full_range: 77..99, 407 full_range: 77..99,
434 focus_range: Some( 408 focus_range: 89..94,
435 89..94,
436 ),
437 name: "bench", 409 name: "bench",
438 kind: FN, 410 kind: Function,
439 container_name: None,
440 description: None,
441 docs: None,
442 }, 411 },
443 kind: Bench { 412 kind: Bench {
444 test_id: Path( 413 test_id: Path(
@@ -528,14 +497,9 @@ struct StructWithRunnable(String);
528 0, 497 0,
529 ), 498 ),
530 full_range: 1..13, 499 full_range: 1..13,
531 focus_range: Some( 500 focus_range: 4..8,
532 4..8,
533 ),
534 name: "main", 501 name: "main",
535 kind: FN, 502 kind: Function,
536 container_name: None,
537 description: None,
538 docs: None,
539 }, 503 },
540 kind: Bin, 504 kind: Bin,
541 cfg: None, 505 cfg: None,
@@ -546,12 +510,7 @@ struct StructWithRunnable(String);
546 0, 510 0,
547 ), 511 ),
548 full_range: 15..74, 512 full_range: 15..74,
549 focus_range: None,
550 name: "should_have_runnable", 513 name: "should_have_runnable",
551 kind: FN,
552 container_name: None,
553 description: None,
554 docs: None,
555 }, 514 },
556 kind: DocTest { 515 kind: DocTest {
557 test_id: Path( 516 test_id: Path(
@@ -566,12 +525,7 @@ struct StructWithRunnable(String);
566 0, 525 0,
567 ), 526 ),
568 full_range: 76..148, 527 full_range: 76..148,
569 focus_range: None,
570 name: "should_have_runnable_1", 528 name: "should_have_runnable_1",
571 kind: FN,
572 container_name: None,
573 description: None,
574 docs: None,
575 }, 529 },
576 kind: DocTest { 530 kind: DocTest {
577 test_id: Path( 531 test_id: Path(
@@ -586,12 +540,7 @@ struct StructWithRunnable(String);
586 0, 540 0,
587 ), 541 ),
588 full_range: 150..254, 542 full_range: 150..254,
589 focus_range: None,
590 name: "should_have_runnable_2", 543 name: "should_have_runnable_2",
591 kind: FN,
592 container_name: None,
593 description: None,
594 docs: None,
595 }, 544 },
596 kind: DocTest { 545 kind: DocTest {
597 test_id: Path( 546 test_id: Path(
@@ -606,12 +555,7 @@ struct StructWithRunnable(String);
606 0, 555 0,
607 ), 556 ),
608 full_range: 756..821, 557 full_range: 756..821,
609 focus_range: None,
610 name: "StructWithRunnable", 558 name: "StructWithRunnable",
611 kind: STRUCT,
612 container_name: None,
613 description: None,
614 docs: None,
615 }, 559 },
616 kind: DocTest { 560 kind: DocTest {
617 test_id: Path( 561 test_id: Path(
@@ -650,14 +594,9 @@ impl Data {
650 0, 594 0,
651 ), 595 ),
652 full_range: 1..13, 596 full_range: 1..13,
653 focus_range: Some( 597 focus_range: 4..8,
654 4..8,
655 ),
656 name: "main", 598 name: "main",
657 kind: FN, 599 kind: Function,
658 container_name: None,
659 description: None,
660 docs: None,
661 }, 600 },
662 kind: Bin, 601 kind: Bin,
663 cfg: None, 602 cfg: None,
@@ -668,12 +607,7 @@ impl Data {
668 0, 607 0,
669 ), 608 ),
670 full_range: 44..98, 609 full_range: 44..98,
671 focus_range: None,
672 name: "foo", 610 name: "foo",
673 kind: FN,
674 container_name: None,
675 description: None,
676 docs: None,
677 }, 611 },
678 kind: DocTest { 612 kind: DocTest {
679 test_id: Path( 613 test_id: Path(
@@ -707,14 +641,9 @@ mod test_mod {
707 0, 641 0,
708 ), 642 ),
709 full_range: 1..51, 643 full_range: 1..51,
710 focus_range: Some( 644 focus_range: 5..13,
711 5..13,
712 ),
713 name: "test_mod", 645 name: "test_mod",
714 kind: MODULE, 646 kind: Module,
715 container_name: None,
716 description: None,
717 docs: None,
718 }, 647 },
719 kind: TestMod { 648 kind: TestMod {
720 path: "test_mod", 649 path: "test_mod",
@@ -727,14 +656,9 @@ mod test_mod {
727 0, 656 0,
728 ), 657 ),
729 full_range: 20..49, 658 full_range: 20..49,
730 focus_range: Some( 659 focus_range: 35..44,
731 35..44,
732 ),
733 name: "test_foo1", 660 name: "test_foo1",
734 kind: FN, 661 kind: Function,
735 container_name: None,
736 description: None,
737 docs: None,
738 }, 662 },
739 kind: Test { 663 kind: Test {
740 test_id: Path( 664 test_id: Path(
@@ -787,14 +711,9 @@ mod root_tests {
787 0, 711 0,
788 ), 712 ),
789 full_range: 22..323, 713 full_range: 22..323,
790 focus_range: Some( 714 focus_range: 26..40,
791 26..40,
792 ),
793 name: "nested_tests_0", 715 name: "nested_tests_0",
794 kind: MODULE, 716 kind: Module,
795 container_name: None,
796 description: None,
797 docs: None,
798 }, 717 },
799 kind: TestMod { 718 kind: TestMod {
800 path: "root_tests::nested_tests_0", 719 path: "root_tests::nested_tests_0",
@@ -807,14 +726,9 @@ mod root_tests {
807 0, 726 0,
808 ), 727 ),
809 full_range: 51..192, 728 full_range: 51..192,
810 focus_range: Some( 729 focus_range: 55..69,
811 55..69,
812 ),
813 name: "nested_tests_1", 730 name: "nested_tests_1",
814 kind: MODULE, 731 kind: Module,
815 container_name: None,
816 description: None,
817 docs: None,
818 }, 732 },
819 kind: TestMod { 733 kind: TestMod {
820 path: "root_tests::nested_tests_0::nested_tests_1", 734 path: "root_tests::nested_tests_0::nested_tests_1",
@@ -827,14 +741,9 @@ mod root_tests {
827 0, 741 0,
828 ), 742 ),
829 full_range: 84..126, 743 full_range: 84..126,
830 focus_range: Some( 744 focus_range: 107..121,
831 107..121,
832 ),
833 name: "nested_test_11", 745 name: "nested_test_11",
834 kind: FN, 746 kind: Function,
835 container_name: None,
836 description: None,
837 docs: None,
838 }, 747 },
839 kind: Test { 748 kind: Test {
840 test_id: Path( 749 test_id: Path(
@@ -852,14 +761,9 @@ mod root_tests {
852 0, 761 0,
853 ), 762 ),
854 full_range: 140..182, 763 full_range: 140..182,
855 focus_range: Some( 764 focus_range: 163..177,
856 163..177,
857 ),
858 name: "nested_test_12", 765 name: "nested_test_12",
859 kind: FN, 766 kind: Function,
860 container_name: None,
861 description: None,
862 docs: None,
863 }, 767 },
864 kind: Test { 768 kind: Test {
865 test_id: Path( 769 test_id: Path(
@@ -877,14 +781,9 @@ mod root_tests {
877 0, 781 0,
878 ), 782 ),
879 full_range: 202..286, 783 full_range: 202..286,
880 focus_range: Some( 784 focus_range: 206..220,
881 206..220,
882 ),
883 name: "nested_tests_2", 785 name: "nested_tests_2",
884 kind: MODULE, 786 kind: Module,
885 container_name: None,
886 description: None,
887 docs: None,
888 }, 787 },
889 kind: TestMod { 788 kind: TestMod {
890 path: "root_tests::nested_tests_0::nested_tests_2", 789 path: "root_tests::nested_tests_0::nested_tests_2",
@@ -897,14 +796,9 @@ mod root_tests {
897 0, 796 0,
898 ), 797 ),
899 full_range: 235..276, 798 full_range: 235..276,
900 focus_range: Some( 799 focus_range: 258..271,
901 258..271,
902 ),
903 name: "nested_test_2", 800 name: "nested_test_2",
904 kind: FN, 801 kind: Function,
905 container_name: None,
906 description: None,
907 docs: None,
908 }, 802 },
909 kind: Test { 803 kind: Test {
910 test_id: Path( 804 test_id: Path(
@@ -940,14 +834,9 @@ fn test_foo1() {}
940 0, 834 0,
941 ), 835 ),
942 full_range: 1..50, 836 full_range: 1..50,
943 focus_range: Some( 837 focus_range: 36..45,
944 36..45,
945 ),
946 name: "test_foo1", 838 name: "test_foo1",
947 kind: FN, 839 kind: Function,
948 container_name: None,
949 description: None,
950 docs: None,
951 }, 840 },
952 kind: Test { 841 kind: Test {
953 test_id: Path( 842 test_id: Path(
@@ -990,14 +879,9 @@ fn test_foo1() {}
990 0, 879 0,
991 ), 880 ),
992 full_range: 1..72, 881 full_range: 1..72,
993 focus_range: Some( 882 focus_range: 58..67,
994 58..67,
995 ),
996 name: "test_foo1", 883 name: "test_foo1",
997 kind: FN, 884 kind: Function,
998 container_name: None,
999 description: None,
1000 docs: None,
1001 }, 885 },
1002 kind: Test { 886 kind: Test {
1003 test_id: Path( 887 test_id: Path(
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 488969f1a..00c717c7c 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -23,7 +23,7 @@ use crate::{
23 syntax_highlighting::{ 23 syntax_highlighting::{
24 format::FormatStringHighlighter, macro_rules::MacroRulesHighlighter, tags::Highlight, 24 format::FormatStringHighlighter, macro_rules::MacroRulesHighlighter, tags::Highlight,
25 }, 25 },
26 FileId, HighlightModifier, HighlightTag, 26 FileId, HighlightModifier, HighlightTag, SymbolKind,
27}; 27};
28 28
29pub(crate) use html::highlight_as_html; 29pub(crate) use html::highlight_as_html;
@@ -103,7 +103,7 @@ pub(crate) fn highlight(
103 if let Some(range) = macro_call_range(&mc) { 103 if let Some(range) = macro_call_range(&mc) {
104 stack.add(HighlightedRange { 104 stack.add(HighlightedRange {
105 range, 105 range,
106 highlight: HighlightTag::Macro.into(), 106 highlight: HighlightTag::Symbol(SymbolKind::Macro).into(),
107 binding_hash: None, 107 binding_hash: None,
108 }); 108 });
109 } 109 }
@@ -470,13 +470,13 @@ fn highlight_element(
470 }; 470 };
471 471
472 match name_kind { 472 match name_kind {
473 Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), 473 Some(NameClass::ExternCrate(_)) => HighlightTag::Symbol(SymbolKind::Module).into(),
474 Some(NameClass::Definition(def)) => { 474 Some(NameClass::Definition(def)) => {
475 highlight_def(db, def) | HighlightModifier::Definition 475 highlight_def(db, def) | HighlightModifier::Definition
476 } 476 }
477 Some(NameClass::ConstReference(def)) => highlight_def(db, def), 477 Some(NameClass::ConstReference(def)) => highlight_def(db, def),
478 Some(NameClass::PatFieldShorthand { field_ref, .. }) => { 478 Some(NameClass::PatFieldShorthand { field_ref, .. }) => {
479 let mut h = HighlightTag::Field.into(); 479 let mut h = HighlightTag::Symbol(SymbolKind::Field).into();
480 if let Definition::Field(field) = field_ref { 480 if let Definition::Field(field) = field_ref {
481 if let VariantDef::Union(_) = field.parent_def(db) { 481 if let VariantDef::Union(_) = field.parent_def(db) {
482 h |= HighlightModifier::Unsafe; 482 h |= HighlightModifier::Unsafe;
@@ -493,14 +493,16 @@ fn highlight_element(
493 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { 493 NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => {
494 // even though we track whether we are in an attribute or not we still need this special case 494 // even though we track whether we are in an attribute or not we still need this special case
495 // as otherwise we would emit unresolved references for name refs inside attributes 495 // as otherwise we would emit unresolved references for name refs inside attributes
496 Highlight::from(HighlightTag::Function) 496 Highlight::from(HighlightTag::Symbol(SymbolKind::Function))
497 } 497 }
498 NAME_REF => { 498 NAME_REF => {
499 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 499 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
500 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { 500 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
501 match NameRefClass::classify(sema, &name_ref) { 501 match NameRefClass::classify(sema, &name_ref) {
502 Some(name_kind) => match name_kind { 502 Some(name_kind) => match name_kind {
503 NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), 503 NameRefClass::ExternCrate(_) => {
504 HighlightTag::Symbol(SymbolKind::Module).into()
505 }
504 NameRefClass::Definition(def) => { 506 NameRefClass::Definition(def) => {
505 if let Definition::Local(local) = &def { 507 if let Definition::Local(local) = &def {
506 if let Some(name) = local.name(db) { 508 if let Some(name) = local.name(db) {
@@ -530,7 +532,9 @@ fn highlight_element(
530 532
531 h 533 h
532 } 534 }
533 NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), 535 NameRefClass::FieldShorthand { .. } => {
536 HighlightTag::Symbol(SymbolKind::Field).into()
537 }
534 }, 538 },
535 None if syntactic_name_ref_highlighting => { 539 None if syntactic_name_ref_highlighting => {
536 highlight_name_ref_by_syntax(name_ref, sema) 540 highlight_name_ref_by_syntax(name_ref, sema)
@@ -556,7 +560,7 @@ fn highlight_element(
556 CHAR => HighlightTag::CharLiteral.into(), 560 CHAR => HighlightTag::CharLiteral.into(),
557 QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow, 561 QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow,
558 LIFETIME => { 562 LIFETIME => {
559 let h = Highlight::new(HighlightTag::Lifetime); 563 let h = Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam));
560 match element.parent().map(|it| it.kind()) { 564 match element.parent().map(|it| it.kind()) {
561 Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition, 565 Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition,
562 _ => h, 566 _ => h,
@@ -580,7 +584,7 @@ fn highlight_element(
580 HighlightTag::Operator.into() 584 HighlightTag::Operator.into()
581 } 585 }
582 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { 586 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => {
583 HighlightTag::Macro.into() 587 HighlightTag::Symbol(SymbolKind::Macro).into()
584 } 588 }
585 T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => { 589 T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => {
586 HighlightTag::BuiltinType.into() 590 HighlightTag::BuiltinType.into()
@@ -659,7 +663,7 @@ fn highlight_element(
659 .and_then(SyntaxNode::parent) 663 .and_then(SyntaxNode::parent)
660 .and_then(ast::Path::cast) 664 .and_then(ast::Path::cast)
661 .and_then(|p| sema.resolve_path(&p)); 665 .and_then(|p| sema.resolve_path(&p));
662 let mut h = HighlightTag::SelfKeyword.into(); 666 let mut h = HighlightTag::Symbol(SymbolKind::SelfParam).into();
663 if self_param_is_mut 667 if self_param_is_mut
664 || matches!(self_path, 668 || matches!(self_path,
665 Some(hir::PathResolution::Local(local)) 669 Some(hir::PathResolution::Local(local))
@@ -732,7 +736,8 @@ fn highlight_method_call(
732 method_call: &ast::MethodCallExpr, 736 method_call: &ast::MethodCallExpr,
733) -> Option<Highlight> { 737) -> Option<Highlight> {
734 let func = sema.resolve_method_call(&method_call)?; 738 let func = sema.resolve_method_call(&method_call)?;
735 let mut h = HighlightTag::Method.into(); 739 let mut h = HighlightTag::Symbol(SymbolKind::Function).into();
740 h |= HighlightModifier::Associated;
736 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { 741 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
737 h |= HighlightModifier::Unsafe; 742 h |= HighlightModifier::Unsafe;
738 } 743 }
@@ -756,35 +761,45 @@ fn highlight_method_call(
756 761
757fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { 762fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
758 match def { 763 match def {
759 Definition::Macro(_) => HighlightTag::Macro, 764 Definition::Macro(_) => HighlightTag::Symbol(SymbolKind::Macro),
760 Definition::Field(_) => HighlightTag::Field, 765 Definition::Field(_) => HighlightTag::Symbol(SymbolKind::Field),
761 Definition::ModuleDef(def) => match def { 766 Definition::ModuleDef(def) => match def {
762 hir::ModuleDef::Module(_) => HighlightTag::Module, 767 hir::ModuleDef::Module(_) => HighlightTag::Symbol(SymbolKind::Module),
763 hir::ModuleDef::Function(func) => { 768 hir::ModuleDef::Function(func) => {
764 let mut h = if func.as_assoc_item(db).is_some() { 769 let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Function));
770 if func.as_assoc_item(db).is_some() {
771 h |= HighlightModifier::Associated;
765 if func.self_param(db).is_none() { 772 if func.self_param(db).is_none() {
766 Highlight::from(HighlightTag::Method) | HighlightModifier::Static 773 h |= HighlightModifier::Static
767 } else {
768 HighlightTag::Method.into()
769 } 774 }
770 } else { 775 }
771 HighlightTag::Function.into()
772 };
773 if func.is_unsafe(db) { 776 if func.is_unsafe(db) {
774 h |= HighlightModifier::Unsafe; 777 h |= HighlightModifier::Unsafe;
775 } 778 }
776 return h; 779 return h;
777 } 780 }
778 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct, 781 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Symbol(SymbolKind::Struct),
779 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum, 782 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Symbol(SymbolKind::Enum),
780 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union, 783 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Symbol(SymbolKind::Union),
781 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant, 784 hir::ModuleDef::Variant(_) => HighlightTag::Symbol(SymbolKind::Variant),
782 hir::ModuleDef::Const(_) => HighlightTag::Constant, 785 hir::ModuleDef::Const(konst) => {
783 hir::ModuleDef::Trait(_) => HighlightTag::Trait, 786 let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Const));
784 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias, 787 if konst.as_assoc_item(db).is_some() {
788 h |= HighlightModifier::Associated
789 }
790 return h;
791 }
792 hir::ModuleDef::Trait(_) => HighlightTag::Symbol(SymbolKind::Trait),
793 hir::ModuleDef::TypeAlias(type_) => {
794 let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::TypeAlias));
795 if type_.as_assoc_item(db).is_some() {
796 h |= HighlightModifier::Associated
797 }
798 return h;
799 }
785 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType, 800 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType,
786 hir::ModuleDef::Static(s) => { 801 hir::ModuleDef::Static(s) => {
787 let mut h = Highlight::new(HighlightTag::Static); 802 let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Static));
788 if s.is_mut(db) { 803 if s.is_mut(db) {
789 h |= HighlightModifier::Mutable; 804 h |= HighlightModifier::Mutable;
790 h |= HighlightModifier::Unsafe; 805 h |= HighlightModifier::Unsafe;
@@ -792,11 +807,14 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
792 return h; 807 return h;
793 } 808 }
794 }, 809 },
795 Definition::SelfType(_) => HighlightTag::SelfType, 810 Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl),
796 Definition::TypeParam(_) => HighlightTag::TypeParam, 811 Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam),
797 Definition::Local(local) => { 812 Definition::Local(local) => {
798 let tag = 813 let tag = if local.is_param(db) {
799 if local.is_param(db) { HighlightTag::ValueParam } else { HighlightTag::Local }; 814 HighlightTag::Symbol(SymbolKind::ValueParam)
815 } else {
816 HighlightTag::Symbol(SymbolKind::Local)
817 };
800 let mut h = Highlight::new(tag); 818 let mut h = Highlight::new(tag);
801 if local.is_mut(db) || local.ty(db).is_mutable_reference() { 819 if local.is_mut(db) || local.ty(db).is_mutable_reference() {
802 h |= HighlightModifier::Mutable; 820 h |= HighlightModifier::Mutable;
@@ -806,7 +824,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
806 } 824 }
807 return h; 825 return h;
808 } 826 }
809 Definition::LifetimeParam(_) => HighlightTag::Lifetime, 827 Definition::LifetimeParam(_) => HighlightTag::Symbol(SymbolKind::LifetimeParam),
810 } 828 }
811 .into() 829 .into()
812} 830}
@@ -820,19 +838,19 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
820 }; 838 };
821 839
822 let tag = match parent.kind() { 840 let tag = match parent.kind() {
823 STRUCT => HighlightTag::Struct, 841 STRUCT => HighlightTag::Symbol(SymbolKind::Struct),
824 ENUM => HighlightTag::Enum, 842 ENUM => HighlightTag::Symbol(SymbolKind::Enum),
825 UNION => HighlightTag::Union, 843 VARIANT => HighlightTag::Symbol(SymbolKind::Variant),
826 TRAIT => HighlightTag::Trait, 844 UNION => HighlightTag::Symbol(SymbolKind::Union),
827 TYPE_ALIAS => HighlightTag::TypeAlias, 845 TRAIT => HighlightTag::Symbol(SymbolKind::Trait),
828 TYPE_PARAM => HighlightTag::TypeParam, 846 TYPE_ALIAS => HighlightTag::Symbol(SymbolKind::TypeAlias),
829 RECORD_FIELD => HighlightTag::Field, 847 TYPE_PARAM => HighlightTag::Symbol(SymbolKind::TypeParam),
830 MODULE => HighlightTag::Module, 848 RECORD_FIELD => HighlightTag::Symbol(SymbolKind::Field),
831 FN => HighlightTag::Function, 849 MODULE => HighlightTag::Symbol(SymbolKind::Module),
832 CONST => HighlightTag::Constant, 850 FN => HighlightTag::Symbol(SymbolKind::Function),
833 STATIC => HighlightTag::Static, 851 CONST => HighlightTag::Symbol(SymbolKind::Const),
834 VARIANT => HighlightTag::EnumVariant, 852 STATIC => HighlightTag::Symbol(SymbolKind::Static),
835 IDENT_PAT => HighlightTag::Local, 853 IDENT_PAT => HighlightTag::Symbol(SymbolKind::Local),
836 _ => default, 854 _ => default,
837 }; 855 };
838 856
@@ -851,10 +869,10 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
851 METHOD_CALL_EXPR => { 869 METHOD_CALL_EXPR => {
852 return ast::MethodCallExpr::cast(parent) 870 return ast::MethodCallExpr::cast(parent)
853 .and_then(|method_call| highlight_method_call(sema, &method_call)) 871 .and_then(|method_call| highlight_method_call(sema, &method_call))
854 .unwrap_or_else(|| HighlightTag::Function.into()); 872 .unwrap_or_else(|| HighlightTag::Symbol(SymbolKind::Function).into());
855 } 873 }
856 FIELD_EXPR => { 874 FIELD_EXPR => {
857 let h = HighlightTag::Field; 875 let h = HighlightTag::Symbol(SymbolKind::Field);
858 let is_union = ast::FieldExpr::cast(parent) 876 let is_union = ast::FieldExpr::cast(parent)
859 .and_then(|field_expr| { 877 .and_then(|field_expr| {
860 let field = sema.resolve_field(&field_expr)?; 878 let field = sema.resolve_field(&field_expr)?;
@@ -881,9 +899,9 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
881 _ => { 899 _ => {
882 // within path, decide whether it is module or adt by checking for uppercase name 900 // within path, decide whether it is module or adt by checking for uppercase name
883 return if name.text().chars().next().unwrap_or_default().is_uppercase() { 901 return if name.text().chars().next().unwrap_or_default().is_uppercase() {
884 HighlightTag::Struct 902 HighlightTag::Symbol(SymbolKind::Struct)
885 } else { 903 } else {
886 HighlightTag::Module 904 HighlightTag::Symbol(SymbolKind::Module)
887 } 905 }
888 .into(); 906 .into();
889 } 907 }
@@ -894,11 +912,11 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
894 }; 912 };
895 913
896 match parent.kind() { 914 match parent.kind() {
897 CALL_EXPR => HighlightTag::Function.into(), 915 CALL_EXPR => HighlightTag::Symbol(SymbolKind::Function).into(),
898 _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { 916 _ => if name.text().chars().next().unwrap_or_default().is_uppercase() {
899 HighlightTag::Struct.into() 917 HighlightTag::Symbol(SymbolKind::Struct)
900 } else { 918 } else {
901 HighlightTag::Constant 919 HighlightTag::Symbol(SymbolKind::Const)
902 } 920 }
903 .into(), 921 .into(),
904 } 922 }
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs
index 42f27df5d..26416022b 100644
--- a/crates/ide/src/syntax_highlighting/format.rs
+++ b/crates/ide/src/syntax_highlighting/format.rs
@@ -4,7 +4,9 @@ use syntax::{
4 AstNode, AstToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, 4 AstNode, AstToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
5}; 5};
6 6
7use crate::{syntax_highlighting::HighlightedRangeStack, HighlightTag, HighlightedRange}; 7use crate::{
8 syntax_highlighting::HighlightedRangeStack, HighlightTag, HighlightedRange, SymbolKind,
9};
8 10
9#[derive(Default)] 11#[derive(Default)]
10pub(super) struct FormatStringHighlighter { 12pub(super) struct FormatStringHighlighter {
@@ -71,6 +73,6 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HighlightTag> {
71 | FormatSpecifier::Asterisk 73 | FormatSpecifier::Asterisk
72 | FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier, 74 | FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier,
73 FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral, 75 FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral,
74 FormatSpecifier::Identifier => HighlightTag::Local, 76 FormatSpecifier::Identifier => HighlightTag::Symbol(SymbolKind::Local),
75 }) 77 })
76} 78}
diff --git a/crates/ide/src/syntax_highlighting/injection.rs b/crates/ide/src/syntax_highlighting/injection.rs
index e97d1be1a..9eb184c74 100644
--- a/crates/ide/src/syntax_highlighting/injection.rs
+++ b/crates/ide/src/syntax_highlighting/injection.rs
@@ -179,6 +179,5 @@ pub(super) fn highlight_doc_comment(
179 stack.add(comment); 179 stack.add(comment);
180 } 180 }
181 stack.pop_and_inject(None); 181 stack.pop_and_inject(None);
182 stack 182 stack.pop_and_inject(Some(Highlight::from(HighlightTag::Dummy) | HighlightModifier::Injected));
183 .pop_and_inject(Some(Highlight::from(HighlightTag::Generic) | HighlightModifier::Injected));
184} 183}
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index ffd9588b8..974f54fa0 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -3,6 +3,8 @@
3 3
4use std::{fmt, ops}; 4use std::{fmt, ops};
5 5
6use crate::SymbolKind;
7
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
7pub struct Highlight { 9pub struct Highlight {
8 pub tag: HighlightTag, 10 pub tag: HighlightTag,
@@ -14,40 +16,25 @@ pub struct HighlightModifiers(u32);
14 16
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
16pub enum HighlightTag { 18pub enum HighlightTag {
17 Attribute, 19 Symbol(SymbolKind),
20
18 BoolLiteral, 21 BoolLiteral,
19 BuiltinType, 22 BuiltinType,
20 ByteLiteral, 23 ByteLiteral,
21 CharLiteral, 24 CharLiteral,
25 NumericLiteral,
26 StringLiteral,
27 Attribute,
22 Comment, 28 Comment,
23 Constant,
24 Enum,
25 EnumVariant,
26 EscapeSequence, 29 EscapeSequence,
27 Field, 30 FormatSpecifier,
28 Function,
29 Generic,
30 Keyword, 31 Keyword,
31 Lifetime,
32 Macro,
33 Method,
34 Module,
35 NumericLiteral,
36 Punctuation, 32 Punctuation,
37 SelfKeyword,
38 SelfType,
39 Static,
40 StringLiteral,
41 Struct,
42 Trait,
43 TypeAlias,
44 TypeParam,
45 Union,
46 ValueParam,
47 Local,
48 UnresolvedReference,
49 FormatSpecifier,
50 Operator, 33 Operator,
34 UnresolvedReference,
35
36 // For things which don't have proper Tag, but want to use modifiers.
37 Dummy,
51} 38}
52 39
53#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 40#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -64,48 +51,53 @@ pub enum HighlightModifier {
64 Injected, 51 Injected,
65 Mutable, 52 Mutable,
66 Consuming, 53 Consuming,
67 Unsafe,
68 Callable, 54 Callable,
69 /// Used for associated functions 55 /// Used for associated functions
70 Static, 56 Static,
57 /// Used for items in impls&traits.
58 Associated,
59
60 /// Keep this last!
61 Unsafe,
71} 62}
72 63
73impl HighlightTag { 64impl HighlightTag {
74 fn as_str(self) -> &'static str { 65 fn as_str(self) -> &'static str {
75 match self { 66 match self {
67 HighlightTag::Symbol(symbol) => match symbol {
68 SymbolKind::Const => "constant",
69 SymbolKind::Static => "static",
70 SymbolKind::Enum => "enum",
71 SymbolKind::Variant => "enum_variant",
72 SymbolKind::Struct => "struct",
73 SymbolKind::Union => "union",
74 SymbolKind::Field => "field",
75 SymbolKind::Module => "module",
76 SymbolKind::Trait => "trait",
77 SymbolKind::Function => "function",
78 SymbolKind::TypeAlias => "type_alias",
79 SymbolKind::TypeParam => "type_param",
80 SymbolKind::LifetimeParam => "lifetime",
81 SymbolKind::Macro => "macro",
82 SymbolKind::Local => "variable",
83 SymbolKind::ValueParam => "value_param",
84 SymbolKind::SelfParam => "self_keyword",
85 SymbolKind::Impl => "self_type",
86 },
76 HighlightTag::Attribute => "attribute", 87 HighlightTag::Attribute => "attribute",
77 HighlightTag::BoolLiteral => "bool_literal", 88 HighlightTag::BoolLiteral => "bool_literal",
78 HighlightTag::BuiltinType => "builtin_type", 89 HighlightTag::BuiltinType => "builtin_type",
79 HighlightTag::ByteLiteral => "byte_literal", 90 HighlightTag::ByteLiteral => "byte_literal",
80 HighlightTag::CharLiteral => "char_literal", 91 HighlightTag::CharLiteral => "char_literal",
81 HighlightTag::Comment => "comment", 92 HighlightTag::Comment => "comment",
82 HighlightTag::Constant => "constant",
83 HighlightTag::Enum => "enum",
84 HighlightTag::EnumVariant => "enum_variant",
85 HighlightTag::EscapeSequence => "escape_sequence", 93 HighlightTag::EscapeSequence => "escape_sequence",
86 HighlightTag::Field => "field",
87 HighlightTag::FormatSpecifier => "format_specifier", 94 HighlightTag::FormatSpecifier => "format_specifier",
88 HighlightTag::Function => "function", 95 HighlightTag::Dummy => "dummy",
89 HighlightTag::Generic => "generic",
90 HighlightTag::Keyword => "keyword", 96 HighlightTag::Keyword => "keyword",
91 HighlightTag::Lifetime => "lifetime",
92 HighlightTag::Punctuation => "punctuation", 97 HighlightTag::Punctuation => "punctuation",
93 HighlightTag::Macro => "macro",
94 HighlightTag::Method => "method",
95 HighlightTag::Module => "module",
96 HighlightTag::NumericLiteral => "numeric_literal", 98 HighlightTag::NumericLiteral => "numeric_literal",
97 HighlightTag::Operator => "operator", 99 HighlightTag::Operator => "operator",
98 HighlightTag::SelfKeyword => "self_keyword",
99 HighlightTag::SelfType => "self_type",
100 HighlightTag::Static => "static",
101 HighlightTag::StringLiteral => "string_literal", 100 HighlightTag::StringLiteral => "string_literal",
102 HighlightTag::Struct => "struct",
103 HighlightTag::Trait => "trait",
104 HighlightTag::TypeAlias => "type_alias",
105 HighlightTag::TypeParam => "type_param",
106 HighlightTag::Union => "union",
107 HighlightTag::ValueParam => "value_param",
108 HighlightTag::Local => "variable",
109 HighlightTag::UnresolvedReference => "unresolved_reference", 101 HighlightTag::UnresolvedReference => "unresolved_reference",
110 } 102 }
111 } 103 }
@@ -118,7 +110,7 @@ impl fmt::Display for HighlightTag {
118} 110}
119 111
120impl HighlightModifier { 112impl HighlightModifier {
121 const ALL: &'static [HighlightModifier] = &[ 113 const ALL: &'static [HighlightModifier; HighlightModifier::Unsafe as u8 as usize + 1] = &[
122 HighlightModifier::Attribute, 114 HighlightModifier::Attribute,
123 HighlightModifier::ControlFlow, 115 HighlightModifier::ControlFlow,
124 HighlightModifier::Definition, 116 HighlightModifier::Definition,
@@ -126,9 +118,10 @@ impl HighlightModifier {
126 HighlightModifier::Injected, 118 HighlightModifier::Injected,
127 HighlightModifier::Mutable, 119 HighlightModifier::Mutable,
128 HighlightModifier::Consuming, 120 HighlightModifier::Consuming,
129 HighlightModifier::Unsafe,
130 HighlightModifier::Callable, 121 HighlightModifier::Callable,
131 HighlightModifier::Static, 122 HighlightModifier::Static,
123 HighlightModifier::Associated,
124 HighlightModifier::Unsafe,
132 ]; 125 ];
133 126
134 fn as_str(self) -> &'static str { 127 fn as_str(self) -> &'static str {
@@ -143,6 +136,7 @@ impl HighlightModifier {
143 HighlightModifier::Unsafe => "unsafe", 136 HighlightModifier::Unsafe => "unsafe",
144 HighlightModifier::Callable => "callable", 137 HighlightModifier::Callable => "callable",
145 HighlightModifier::Static => "static", 138 HighlightModifier::Static => "static",
139 HighlightModifier::Associated => "associated",
146 } 140 }
147 } 141 }
148 142
@@ -209,6 +203,10 @@ impl ops::BitOr<HighlightModifier> for Highlight {
209} 203}
210 204
211impl HighlightModifiers { 205impl HighlightModifiers {
206 pub fn contains(self, m: HighlightModifier) -> bool {
207 self.0 & m.mask() == m.mask()
208 }
209
212 pub fn iter(self) -> impl Iterator<Item = HighlightModifier> { 210 pub fn iter(self) -> impl Iterator<Item = HighlightModifier> {
213 HighlightModifier::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask()) 211 HighlightModifier::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask())
214 } 212 }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index 6fb606a47..db6f32d33 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -40,17 +40,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
40<span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="punctuation">{</span><span class="punctuation">}</span> 40<span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="punctuation">{</span><span class="punctuation">}</span>
41 41
42<span class="keyword">impl</span> <span class="struct">foo</span> <span class="punctuation">{</span> 42<span class="keyword">impl</span> <span class="struct">foo</span> <span class="punctuation">{</span>
43 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration static">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 43 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
44 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 44 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</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">trait</span> <span class="trait declaration">t</span> <span class="punctuation">{</span> 47<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="punctuation">{</span>
48 <span class="keyword">fn</span> <span class="method declaration static">t_is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 48 <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
49 <span class="keyword">fn</span> <span class="method declaration">t_is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 49 <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
50<span class="punctuation">}</span> 50<span class="punctuation">}</span>
51 51
52<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="punctuation">{</span> 52<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="punctuation">{</span>
53 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration static">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 53 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
54 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 54 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
55<span class="punctuation">}</span> 55<span class="punctuation">}</span>
56 </code></pre> \ No newline at end of file 56 </code></pre> \ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 920956b51..4e511baa9 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -36,24 +36,24 @@ 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="comment documentation">/// ```</span> 38<pre><code><span class="comment documentation">/// ```</span>
39<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="punctuation injected">_</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="punctuation injected">;</span><span class="punctuation injected"> 39<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="punctuation injected">_</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="punctuation injected">;</span><span class="punctuation injected">
40</span><span class="comment documentation">/// ```</span> 40</span><span class="comment documentation">/// ```</span>
41<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> 41<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
42 <span class="field declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span><span class="punctuation">,</span> 42 <span class="field declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span><span class="punctuation">,</span>
43<span class="punctuation">}</span> 43<span class="punctuation">}</span>
44 44
45<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> 45<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
46 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="punctuation">;</span> 46 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration associated">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="punctuation">;</span>
47 47
48 <span class="comment documentation">/// Constructs a new `Foo`.</span> 48 <span class="comment documentation">/// Constructs a new `Foo`.</span>
49 <span class="comment documentation">///</span> 49 <span class="comment documentation">///</span>
50 <span class="comment documentation">/// # Examples</span> 50 <span class="comment documentation">/// # Examples</span>
51 <span class="comment documentation">///</span> 51 <span class="comment documentation">///</span>
52 <span class="comment documentation">/// ```</span> 52 <span class="comment documentation">/// ```</span>
53 <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="punctuation attribute injected">)</span><span class="attribute attribute injected">]</span> 53 <span class="comment documentation">/// #</span><span class="dummy injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="punctuation attribute injected">)</span><span class="attribute attribute injected">]</span>
54 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> 54 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="keyword injected">mut</span><span class="dummy injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
55</span> <span class="comment documentation">/// ```</span> 55</span> <span class="comment documentation">/// ```</span>
56 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="method declaration static">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span> 56 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static associated">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
57 <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">bar</span><span class="punctuation">:</span> <span class="bool_literal">true</span> <span class="punctuation">}</span> 57 <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">bar</span><span class="punctuation">:</span> <span class="bool_literal">true</span> <span class="punctuation">}</span>
58 <span class="punctuation">}</span> 58 <span class="punctuation">}</span>
59 59
@@ -62,32 +62,32 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
62 <span class="comment documentation">/// # Examples</span> 62 <span class="comment documentation">/// # Examples</span>
63 <span class="comment documentation">///</span> 63 <span class="comment documentation">///</span>
64 <span class="comment documentation">/// ```</span> 64 <span class="comment documentation">/// ```</span>
65 <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="generic injected"> </span><span class="module injected">x</span><span class="operator injected">::</span><span class="module injected">y</span><span class="punctuation injected">;</span> 65 <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="dummy injected"> </span><span class="module injected">x</span><span class="operator injected">::</span><span class="module injected">y</span><span class="punctuation injected">;</span>
66 <span class="comment documentation">///</span> 66 <span class="comment documentation">///</span>
67 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span> 67 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">foo</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
68 <span class="comment documentation">///</span> 68 <span class="comment documentation">///</span>
69 <span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span> 69 <span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span>
70 <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="punctuation injected">(</span><span class="generic injected">foo</span><span class="operator injected">.</span><span class="generic injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span> 70 <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="punctuation injected">(</span><span class="dummy injected">foo</span><span class="operator injected">.</span><span class="dummy injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
71 <span class="comment documentation">///</span> 71 <span class="comment documentation">///</span>
72 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">bar</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="generic injected"> </span><span class="operator injected">||</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="punctuation injected">;</span> 72 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">bar</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="dummy injected"> </span><span class="operator injected">||</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="punctuation injected">;</span>
73 <span class="comment documentation">///</span> 73 <span class="comment documentation">///</span>
74 <span class="comment documentation">/// </span><span class="comment injected">/* multi-line 74 <span class="comment documentation">/// </span><span class="comment injected">/* multi-line
75 </span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span> 75 </span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span>
76 <span class="comment documentation">///</span> 76 <span class="comment documentation">///</span>
77 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="string_literal injected">"Foo 77 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="string_literal injected">"Foo
78 </span><span class="comment documentation">/// </span><span class="string_literal injected"> bar 78 </span><span class="comment documentation">/// </span><span class="string_literal injected"> bar
79 </span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="punctuation injected">;</span> 79 </span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="punctuation injected">;</span>
80 <span class="comment documentation">///</span> 80 <span class="comment documentation">///</span>
81 <span class="comment documentation">/// ```</span> 81 <span class="comment documentation">/// ```</span>
82 <span class="comment documentation">///</span> 82 <span class="comment documentation">///</span>
83 <span class="comment documentation">/// ```rust,no_run</span> 83 <span class="comment documentation">/// ```rust,no_run</span>
84 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foobar</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> 84 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">foobar</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
85</span> <span class="comment documentation">/// ```</span> 85</span> <span class="comment documentation">/// ```</span>
86 <span class="comment documentation">///</span> 86 <span class="comment documentation">///</span>
87 <span class="comment documentation">/// ```sh</span> 87 <span class="comment documentation">/// ```sh</span>
88 <span class="comment documentation">/// echo 1</span> 88 <span class="comment documentation">/// echo 1</span>
89 <span class="comment documentation">/// ```</span> 89 <span class="comment documentation">/// ```</span>
90 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration">foo</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="punctuation">{</span> 90 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="punctuation">{</span>
91 <span class="bool_literal">true</span> 91 <span class="bool_literal">true</span>
92 <span class="punctuation">}</span> 92 <span class="punctuation">}</span>
93<span class="punctuation">}</span> 93<span class="punctuation">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 31daf2bd0..7f18ad297 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -40,7 +40,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
40<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> 40<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
41 <span class="function">fixture</span><span class="punctuation">(</span><span class="string_literal">r#"</span> 41 <span class="function">fixture</span><span class="punctuation">(</span><span class="string_literal">r#"</span>
42 <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="punctuation">{</span> 42 <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="punctuation">{</span>
43 <span class="keyword">fn</span> <span class="method declaration static">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> 43 <span class="keyword">fn</span> <span class="function declaration static associated">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
44 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span> 44 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span>
45 <span class="punctuation">}</span> 45 <span class="punctuation">}</span>
46 <span class="punctuation">}</span><span class="string_literal">"#</span> 46 <span class="punctuation">}</span><span class="string_literal">"#</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 67ec73f15..d26f48516 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -45,7 +45,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
45<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> 45<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span>
46 46
47<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> 47<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span>
48 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="method declaration unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 48 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
49<span class="punctuation">}</span> 49<span class="punctuation">}</span>
50 50
51<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="punctuation">{</span> 51<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="punctuation">{</span>
@@ -60,11 +60,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
60<span class="punctuation">}</span> 60<span class="punctuation">}</span>
61 61
62<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span> 62<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span>
63 <span class="keyword">fn</span> <span class="method declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span> 63 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span>
64<span class="punctuation">}</span> 64<span class="punctuation">}</span>
65 65
66<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span> 66<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span>
67 <span class="keyword">fn</span> <span class="method declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> 67 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
68<span class="punctuation">}</span> 68<span class="punctuation">}</span>
69 69
70<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> 70<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
@@ -78,7 +78,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
78 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> 78 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
79 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> 79 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
80 <span class="punctuation">}</span> 80 <span class="punctuation">}</span>
81 <span class="struct">HasUnsafeFn</span><span class="operator">.</span><span class="method unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 81 <span class="struct">HasUnsafeFn</span><span class="operator">.</span><span class="function associated unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
82 82
83 <span class="comment">// unsafe deref</span> 83 <span class="comment">// unsafe deref</span>
84 <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span> 84 <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span>
@@ -94,6 +94,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
94 <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> 94 <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span>
95 95
96 <span class="comment">// unsafe auto ref of packed field</span> 96 <span class="comment">// unsafe auto ref of packed field</span>
97 <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="method unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 97 <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
98 <span class="punctuation">}</span> 98 <span class="punctuation">}</span>
99<span class="punctuation">}</span></code></pre> \ No newline at end of file 99<span class="punctuation">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 3530a5fdb..588e86a34 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -65,25 +65,25 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
65<span class="punctuation">}</span> 65<span class="punctuation">}</span>
66 66
67<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="punctuation">{</span> 67<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="punctuation">{</span>
68 <span class="keyword">fn</span> <span class="method declaration">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="punctuation">;</span> 68 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="punctuation">;</span>
69<span class="punctuation">}</span> 69<span class="punctuation">}</span>
70 70
71<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="punctuation">{</span> 71<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
72 <span class="keyword">fn</span> <span class="method declaration">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> 72 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
73 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 73 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
74 <span class="punctuation">}</span> 74 <span class="punctuation">}</span>
75<span class="punctuation">}</span> 75<span class="punctuation">}</span>
76 76
77<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> 77<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
78 <span class="keyword">fn</span> <span class="method declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> 78 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
79 <span class="value_param">f</span><span class="operator">.</span><span class="method consuming">baz</span><span class="punctuation">(</span><span class="self_keyword mutable consuming">self</span><span class="punctuation">)</span> 79 <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="punctuation">(</span><span class="self_keyword mutable consuming">self</span><span class="punctuation">)</span>
80 <span class="punctuation">}</span> 80 <span class="punctuation">}</span>
81 81
82 <span class="keyword">fn</span> <span class="method declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> 82 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
83 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> 83 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
84 <span class="punctuation">}</span> 84 <span class="punctuation">}</span>
85 85
86 <span class="keyword">fn</span> <span class="method declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> 86 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
87 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 87 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
88 <span class="punctuation">}</span> 88 <span class="punctuation">}</span>
89<span class="punctuation">}</span> 89<span class="punctuation">}</span>
@@ -94,15 +94,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
94<span class="punctuation">}</span> 94<span class="punctuation">}</span>
95 95
96<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> 96<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span>
97 <span class="keyword">fn</span> <span class="method declaration">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">FooCopy</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span> 97 <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">FooCopy</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
98 <span class="value_param">f</span><span class="operator">.</span><span class="method">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span> 98 <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span>
99 <span class="punctuation">}</span> 99 <span class="punctuation">}</span>
100 100
101 <span class="keyword">fn</span> <span class="method declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> 101 <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
102 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> 102 <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
103 <span class="punctuation">}</span> 103 <span class="punctuation">}</span>
104 104
105 <span class="keyword">fn</span> <span class="method declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span> 105 <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
106 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 106 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
107 <span class="punctuation">}</span> 107 <span class="punctuation">}</span>
108<span class="punctuation">}</span> 108<span class="punctuation">}</span>
@@ -178,17 +178,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
178 178
179 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span> 179 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
180 <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span> 180 <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
181 <span class="variable mutable">foo</span><span class="operator">.</span><span class="method">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 181 <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
182 <span class="variable mutable">foo</span><span class="operator">.</span><span class="method mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 182 <span class="variable mutable">foo</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
183 <span class="variable mutable">foo</span><span class="operator">.</span><span class="method consuming">baz</span><span class="punctuation">(</span><span class="variable consuming">foo2</span><span class="punctuation">)</span><span class="punctuation">;</span> 183 <span class="variable mutable">foo</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="punctuation">(</span><span class="variable consuming">foo2</span><span class="punctuation">)</span><span class="punctuation">;</span>
184 184
185 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> <span class="field">x</span> <span class="punctuation">}</span><span class="punctuation">;</span> 185 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> <span class="field">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
186 <span class="variable mutable">copy</span><span class="operator">.</span><span class="method">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 186 <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
187 <span class="variable mutable">copy</span><span class="operator">.</span><span class="method mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 187 <span class="variable mutable">copy</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
188 <span class="variable mutable">copy</span><span class="operator">.</span><span class="method">baz</span><span class="punctuation">(</span><span class="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span> 188 <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="punctuation">(</span><span class="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span>
189 189
190 <span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="punctuation">;</span> 190 <span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="punctuation">;</span>
191 <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="method">baz</span><span class="punctuation">;</span> 191 <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated">baz</span><span class="punctuation">;</span>
192 192
193 <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="punctuation">;</span> 193 <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="punctuation">;</span>
194 <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="punctuation">;</span> 194 <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="punctuation">;</span>
@@ -203,7 +203,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
203<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="punctuation">;</span> 203<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="punctuation">;</span>
204 204
205<span class="keyword">impl</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="type_param">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 205<span class="keyword">impl</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="type_param">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
206 <span class="keyword">fn</span> <span class="method declaration">and</span><span class="punctuation">&lt;</span><span class="type_param declaration">U</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">other</span><span class="punctuation">:</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="type_param">U</span><span class="punctuation">&gt;</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">,</span> <span class="type_param">U</span><span class="punctuation">)</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 206 <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="punctuation">&lt;</span><span class="type_param declaration">U</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">other</span><span class="punctuation">:</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="type_param">U</span><span class="punctuation">&gt;</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">,</span> <span class="type_param">U</span><span class="punctuation">)</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
207 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="punctuation">{</span> 207 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="punctuation">{</span>
208 <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> 208 <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="macro">unimplemented!</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
209 <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="punctuation">,</span> 209 <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="punctuation">,</span>
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index bd2afc887..9d7dce1d4 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -66,7 +66,7 @@ impl Definition {
66 hir::Adt::Union(it) => it.name(db), 66 hir::Adt::Union(it) => it.name(db),
67 hir::Adt::Enum(it) => it.name(db), 67 hir::Adt::Enum(it) => it.name(db),
68 }, 68 },
69 hir::ModuleDef::EnumVariant(it) => it.name(db), 69 hir::ModuleDef::Variant(it) => it.name(db),
70 hir::ModuleDef::Const(it) => it.name(db)?, 70 hir::ModuleDef::Const(it) => it.name(db)?,
71 hir::ModuleDef::Static(it) => it.name(db)?, 71 hir::ModuleDef::Static(it) => it.name(db)?,
72 hir::ModuleDef::Trait(it) => it.name(db), 72 hir::ModuleDef::Trait(it) => it.name(db),
@@ -207,7 +207,7 @@ impl NameClass {
207 Some(NameClass::Definition(Definition::ModuleDef(def.into()))) 207 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
208 }, 208 },
209 ast::Variant(it) => { 209 ast::Variant(it) => {
210 let def: hir::EnumVariant = sema.to_def(&it)?; 210 let def: hir::Variant = sema.to_def(&it)?;
211 Some(NameClass::Definition(Definition::ModuleDef(def.into()))) 211 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
212 }, 212 },
213 ast::Fn(it) => { 213 ast::Fn(it) => {
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 9be36d59b..d6b498be3 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -9,7 +9,7 @@ use syntax::{
9 ast::{ 9 ast::{
10 self, 10 self,
11 edit::{AstNodeEdit, IndentLevel}, 11 edit::{AstNodeEdit, IndentLevel},
12 make, AstNode, PathSegmentKind, VisibilityOwner, 12 make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner,
13 }, 13 },
14 AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, 14 AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
15}; 15};
@@ -180,6 +180,15 @@ fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -
180 } 180 }
181} 181}
182 182
183fn eq_attrs(
184 attrs0: impl Iterator<Item = ast::Attr>,
185 attrs1: impl Iterator<Item = ast::Attr>,
186) -> bool {
187 let attrs0 = attrs0.map(|attr| attr.to_string());
188 let attrs1 = attrs1.map(|attr| attr.to_string());
189 attrs0.eq(attrs1)
190}
191
183pub fn try_merge_imports( 192pub fn try_merge_imports(
184 lhs: &ast::Use, 193 lhs: &ast::Use,
185 rhs: &ast::Use, 194 rhs: &ast::Use,
@@ -189,6 +198,10 @@ pub fn try_merge_imports(
189 if !eq_visibility(lhs.visibility(), rhs.visibility()) { 198 if !eq_visibility(lhs.visibility(), rhs.visibility()) {
190 return None; 199 return None;
191 } 200 }
201 if !eq_attrs(lhs.attrs(), rhs.attrs()) {
202 return None;
203 }
204
192 let lhs_tree = lhs.use_tree()?; 205 let lhs_tree = lhs.use_tree()?;
193 let rhs_tree = rhs.use_tree()?; 206 let rhs_tree = rhs.use_tree()?;
194 let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?; 207 let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs
index 9e194354e..a603fe87f 100644
--- a/crates/ide_db/src/helpers/insert_use/tests.rs
+++ b/crates/ide_db/src/helpers/insert_use/tests.rs
@@ -448,6 +448,20 @@ use std::io;",
448} 448}
449 449
450#[test] 450#[test]
451fn merge_groups_skip_attributed() {
452 check_full(
453 "std::io",
454 r#"
455#[cfg(feature = "gated")] use std::fmt::{Result, Display};
456"#,
457 r#"
458#[cfg(feature = "gated")] use std::fmt::{Result, Display};
459use std::io;
460"#,
461 )
462}
463
464#[test]
451#[ignore] // FIXME: Support this 465#[ignore] // FIXME: Support this
452fn split_out_merge() { 466fn split_out_merge() {
453 check_last( 467 check_last(
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 525c8a41f..ff10f71c3 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -141,7 +141,7 @@ impl Definition {
141 hir::GenericDef::Trait(it) => it.source(db).value.syntax().text_range(), 141 hir::GenericDef::Trait(it) => it.source(db).value.syntax().text_range(),
142 hir::GenericDef::TypeAlias(it) => it.source(db).value.syntax().text_range(), 142 hir::GenericDef::TypeAlias(it) => it.source(db).value.syntax().text_range(),
143 hir::GenericDef::Impl(it) => it.source(db).value.syntax().text_range(), 143 hir::GenericDef::Impl(it) => it.source(db).value.syntax().text_range(),
144 hir::GenericDef::EnumVariant(it) => it.source(db).value.syntax().text_range(), 144 hir::GenericDef::Variant(it) => it.source(db).value.syntax().text_range(),
145 hir::GenericDef::Const(it) => it.source(db).value.syntax().text_range(), 145 hir::GenericDef::Const(it) => it.source(db).value.syntax().text_range(),
146 }; 146 };
147 let mut res = FxHashMap::default(); 147 let mut res = FxHashMap::default();
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index ca455fa03..0aa6a0765 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -39,7 +39,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
39use syntax::{ 39use syntax::{
40 ast::{self, NameOwner}, 40 ast::{self, NameOwner},
41 match_ast, AstNode, Parse, SmolStr, SourceFile, 41 match_ast, AstNode, Parse, SmolStr, SourceFile,
42 SyntaxKind::{self, *}, 42 SyntaxKind::*,
43 SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent, 43 SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
44}; 44};
45 45
@@ -323,7 +323,7 @@ impl Query {
323 let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); 323 let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value);
324 324
325 for symbol in &symbol_index.symbols[start..end] { 325 for symbol in &symbol_index.symbols[start..end] {
326 if self.only_types && !is_type(symbol.kind) { 326 if self.only_types && !symbol.kind.is_type() {
327 continue; 327 continue;
328 } 328 }
329 if self.exact && symbol.name != self.query { 329 if self.exact && symbol.name != self.query {
@@ -341,23 +341,44 @@ impl Query {
341 } 341 }
342} 342}
343 343
344fn is_type(kind: SyntaxKind) -> bool {
345 matches!(kind, STRUCT | ENUM | TRAIT | TYPE_ALIAS)
346}
347
348/// The actual data that is stored in the index. It should be as compact as 344/// The actual data that is stored in the index. It should be as compact as
349/// possible. 345/// possible.
350#[derive(Debug, Clone, PartialEq, Eq, Hash)] 346#[derive(Debug, Clone, PartialEq, Eq, Hash)]
351pub struct FileSymbol { 347pub struct FileSymbol {
352 pub file_id: FileId, 348 pub file_id: FileId,
353 pub name: SmolStr, 349 pub name: SmolStr,
354 pub kind: SyntaxKind, 350 pub kind: FileSymbolKind,
355 pub range: TextRange, 351 pub range: TextRange,
356 pub ptr: SyntaxNodePtr, 352 pub ptr: SyntaxNodePtr,
357 pub name_range: Option<TextRange>, 353 pub name_range: Option<TextRange>,
358 pub container_name: Option<SmolStr>, 354 pub container_name: Option<SmolStr>,
359} 355}
360 356
357#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
358pub enum FileSymbolKind {
359 Function,
360 Struct,
361 Enum,
362 Trait,
363 Module,
364 TypeAlias,
365 Const,
366 Static,
367 Macro,
368}
369
370impl FileSymbolKind {
371 fn is_type(self: FileSymbolKind) -> bool {
372 matches!(
373 self,
374 FileSymbolKind::Struct
375 | FileSymbolKind::Enum
376 | FileSymbolKind::Trait
377 | FileSymbolKind::TypeAlias
378 )
379 }
380}
381
361fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> { 382fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> {
362 let mut symbols = Vec::new(); 383 let mut symbols = Vec::new();
363 let mut stack = Vec::new(); 384 let mut stack = Vec::new();
@@ -412,7 +433,18 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
412fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> { 433fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
413 to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol { 434 to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol {
414 name, 435 name,
415 kind: node.kind(), 436 kind: match node.kind() {
437 FN => FileSymbolKind::Function,
438 STRUCT => FileSymbolKind::Struct,
439 ENUM => FileSymbolKind::Enum,
440 TRAIT => FileSymbolKind::Trait,
441 MODULE => FileSymbolKind::Module,
442 TYPE_ALIAS => FileSymbolKind::TypeAlias,
443 CONST => FileSymbolKind::Const,
444 STATIC => FileSymbolKind::Static,
445 MACRO_RULES => FileSymbolKind::Macro,
446 kind => unreachable!("{:?}", kind),
447 },
416 range: node.text_range(), 448 range: node.text_range(),
417 ptr, 449 ptr,
418 file_id, 450 file_id,
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs
index 616119ba9..57592dc92 100644
--- a/crates/mbe/src/mbe_expander/transcriber.rs
+++ b/crates/mbe/src/mbe_expander/transcriber.rs
@@ -97,7 +97,7 @@ fn expand_subtree(
97 err = err.or(e); 97 err = err.or(e);
98 arena.push(tt.into()); 98 arena.push(tt.into());
99 } 99 }
100 Op::Var { name, kind: _ } => { 100 Op::Var { name, .. } => {
101 let ExpandResult { value: fragment, err: e } = expand_var(ctx, name); 101 let ExpandResult { value: fragment, err: e } = expand_var(ctx, name);
102 err = err.or(e); 102 err = err.or(e);
103 push_fragment(arena, fragment); 103 push_fragment(arena, fragment);
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index 6b46a1673..c3fdd4040 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -101,7 +101,9 @@ fn next_op<'a>(
101 Op::Repeat { subtree, separator, kind } 101 Op::Repeat { subtree, separator, kind }
102 } 102 }
103 tt::TokenTree::Leaf(leaf) => match leaf { 103 tt::TokenTree::Leaf(leaf) => match leaf {
104 tt::Leaf::Punct(..) => return Err(ExpandError::UnexpectedToken), 104 tt::Leaf::Punct(_) => {
105 return Err(ExpandError::UnexpectedToken);
106 }
105 tt::Leaf::Ident(ident) => { 107 tt::Leaf::Ident(ident) => {
106 let name = &ident.text; 108 let name = &ident.text;
107 let kind = eat_fragment_kind(src, mode)?; 109 let kind = eat_fragment_kind(src, mode)?;
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 265c0d63d..2bec7fd49 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -313,7 +313,7 @@ trait TokenConvertor {
313 return; 313 return;
314 } 314 }
315 315
316 result.push(if k.is_punct() { 316 result.push(if k.is_punct() && k != UNDERSCORE {
317 assert_eq!(range.len(), TextSize::of('.')); 317 assert_eq!(range.len(), TextSize::of('.'));
318 let delim = match k { 318 let delim = match k {
319 T!['('] => Some((tt::DelimiterKind::Parenthesis, T![')'])), 319 T!['('] => Some((tt::DelimiterKind::Parenthesis, T![')'])),
@@ -378,6 +378,7 @@ trait TokenConvertor {
378 let leaf: tt::Leaf = match k { 378 let leaf: tt::Leaf = match k {
379 T![true] | T![false] => make_leaf!(Ident), 379 T![true] | T![false] => make_leaf!(Ident),
380 IDENT => make_leaf!(Ident), 380 IDENT => make_leaf!(Ident),
381 UNDERSCORE => make_leaf!(Ident),
381 k if k.is_keyword() => make_leaf!(Ident), 382 k if k.is_keyword() => make_leaf!(Ident),
382 k if k.is_literal() => make_leaf!(Literal), 383 k if k.is_literal() => make_leaf!(Literal),
383 LIFETIME_IDENT => { 384 LIFETIME_IDENT => {
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index dff6e98c2..f10e7a9b6 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -992,6 +992,18 @@ fn test_tt_composite2() {
992} 992}
993 993
994#[test] 994#[test]
995fn test_underscore() {
996 parse_macro(
997 r#"
998 macro_rules! foo {
999 ($_:tt) => { 0 }
1000 }
1001 "#,
1002 )
1003 .assert_expand_items(r#"foo! { => }"#, r#"0"#);
1004}
1005
1006#[test]
995fn test_lifetime() { 1007fn test_lifetime() {
996 parse_macro( 1008 parse_macro(
997 r#" 1009 r#"
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 23039eba4..1a078f6b4 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -133,6 +133,10 @@ pub(crate) mod fragments {
133 133
134 m.complete(p, MACRO_STMTS); 134 m.complete(p, MACRO_STMTS);
135 } 135 }
136
137 pub(crate) fn attr(p: &mut Parser) {
138 attributes::outer_attrs(p)
139 }
136} 140}
137 141
138pub(crate) fn reparser( 142pub(crate) fn reparser(
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 41e62116f..ab8e4c70e 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -99,6 +99,8 @@ pub enum FragmentKind {
99 // FIXME: use separate fragment kinds for macro inputs and outputs? 99 // FIXME: use separate fragment kinds for macro inputs and outputs?
100 Items, 100 Items,
101 Statements, 101 Statements,
102
103 Attr,
102} 104}
103 105
104pub fn parse_fragment( 106pub fn parse_fragment(
@@ -118,6 +120,7 @@ pub fn parse_fragment(
118 FragmentKind::Statement => grammar::fragments::stmt, 120 FragmentKind::Statement => grammar::fragments::stmt,
119 FragmentKind::Items => grammar::fragments::macro_items, 121 FragmentKind::Items => grammar::fragments::macro_items,
120 FragmentKind::Statements => grammar::fragments::macro_stmts, 122 FragmentKind::Statements => grammar::fragments::macro_stmts,
123 FragmentKind::Attr => grammar::fragments::attr,
121 }; 124 };
122 parse_from_tokens(token_source, tree_sink, parser) 125 parse_from_tokens(token_source, tree_sink, parser)
123} 126}
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index 894c5c952..bb3b6f2ef 100644
--- a/crates/project_model/src/cargo_workspace.rs
+++ b/crates/project_model/src/cargo_workspace.rs
@@ -16,6 +16,7 @@ use paths::{AbsPath, AbsPathBuf};
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17 17
18use crate::cfg_flag::CfgFlag; 18use crate::cfg_flag::CfgFlag;
19use crate::utf8_stdout;
19 20
20/// `CargoWorkspace` represents the logical structure of, well, a Cargo 21/// `CargoWorkspace` represents the logical structure of, well, a Cargo
21/// workspace. It pretty closely mirrors `cargo metadata` output. 22/// workspace. It pretty closely mirrors `cargo metadata` output.
@@ -166,8 +167,34 @@ impl CargoWorkspace {
166 if let Some(parent) = cargo_toml.parent() { 167 if let Some(parent) = cargo_toml.parent() {
167 meta.current_dir(parent.to_path_buf()); 168 meta.current_dir(parent.to_path_buf());
168 } 169 }
169 if let Some(target) = config.target.as_ref() { 170 let target = if let Some(target) = config.target.as_ref() {
170 meta.other_options(vec![String::from("--filter-platform"), target.clone()]); 171 Some(target.clone())
172 } else {
173 // cargo metadata defaults to giving information for _all_ targets.
174 // In the absence of a preference from the user, we use the host platform.
175 let mut rustc = Command::new(toolchain::rustc());
176 rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV");
177 log::debug!("Discovering host platform by {:?}", rustc);
178 match utf8_stdout(rustc) {
179 Ok(stdout) => {
180 let field = "host: ";
181 let target = stdout.lines().find_map(|l| l.strip_prefix(field));
182 if let Some(target) = target {
183 Some(target.to_string())
184 } else {
185 // If we fail to resolve the host platform, it's not the end of the world.
186 log::info!("rustc -vV did not report host platform, got:\n{}", stdout);
187 None
188 }
189 }
190 Err(e) => {
191 log::warn!("Failed to discover host platform: {}", e);
192 None
193 }
194 }
195 };
196 if let Some(target) = target {
197 meta.other_options(vec![String::from("--filter-platform"), target]);
171 } 198 }
172 let mut meta = meta.exec().with_context(|| { 199 let mut meta = meta.exec().with_context(|| {
173 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) 200 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display())
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 039976e4b..0b4d3f4eb 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -21,7 +21,7 @@ env_logger = { version = "0.8.1", default-features = false }
21itertools = "0.9.0" 21itertools = "0.9.0"
22jod-thread = "0.1.0" 22jod-thread = "0.1.0"
23log = "0.4.8" 23log = "0.4.8"
24lsp-types = { version = "0.85.0", features = ["proposed"] } 24lsp-types = { version = "0.86.0", features = ["proposed"] }
25parking_lot = "0.11.0" 25parking_lot = "0.11.0"
26pico-args = "0.3.1" 26pico-args = "0.3.1"
27oorandom = "11.1.2" 27oorandom = "11.1.2"
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 5e4c22bc5..de5eb93b5 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -64,7 +64,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
64 prepare_provider: Some(true), 64 prepare_provider: Some(true),
65 work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, 65 work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
66 })), 66 })),
67 on_type_rename_provider: None, 67 linked_editing_range_provider: None,
68 document_link_provider: None, 68 document_link_provider: None,
69 color_provider: None, 69 color_provider: None,
70 execute_command_provider: None, 70 execute_command_provider: None,
@@ -83,6 +83,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
83 } 83 }
84 .into(), 84 .into(),
85 ), 85 ),
86 moniker_provider: None,
86 experimental: Some(json!({ 87 experimental: Some(json!({
87 "joinLines": true, 88 "joinLines": true,
88 "ssr": true, 89 "ssr": true,
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index af226c109..66f8bee99 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -9,7 +9,7 @@ use std::{
9 9
10use ide::{ 10use ide::{
11 CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, 11 CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
12 NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, 12 NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SymbolKind, TextEdit,
13}; 13};
14use itertools::Itertools; 14use itertools::Itertools;
15use lsp_server::ErrorCode; 15use lsp_server::ErrorCode;
@@ -27,7 +27,7 @@ use project_model::TargetKind;
27use serde::{Deserialize, Serialize}; 27use serde::{Deserialize, Serialize};
28use serde_json::to_value; 28use serde_json::to_value;
29use stdx::{format_to, split_once}; 29use stdx::{format_to, split_once};
30use syntax::{algo, ast, AstNode, SyntaxKind, TextRange, TextSize}; 30use syntax::{algo, ast, AstNode, TextRange, TextSize};
31 31
32use crate::{ 32use crate::{
33 cargo_target_spec::CargoTargetSpec, 33 cargo_target_spec::CargoTargetSpec,
@@ -385,7 +385,10 @@ pub(crate) fn handle_workspace_symbol(
385 #[allow(deprecated)] 385 #[allow(deprecated)]
386 let info = SymbolInformation { 386 let info = SymbolInformation {
387 name: nav.name.to_string(), 387 name: nav.name.to_string(),
388 kind: to_proto::symbol_kind(nav.kind), 388 kind: nav
389 .kind
390 .map(to_proto::symbol_kind)
391 .unwrap_or(lsp_types::SymbolKind::Variable),
389 tags: None, 392 tags: None,
390 location: to_proto::location_from_nav(snap, nav)?, 393 location: to_proto::location_from_nav(snap, nav)?,
391 container_name, 394 container_name,
@@ -1037,10 +1040,10 @@ pub(crate) fn handle_code_lens(
1037 .filter(|it| { 1040 .filter(|it| {
1038 matches!( 1041 matches!(
1039 it.kind, 1042 it.kind,
1040 SyntaxKind::TRAIT 1043 SymbolKind::Trait
1041 | SyntaxKind::STRUCT 1044 | SymbolKind::Struct
1042 | SyntaxKind::ENUM 1045 | SymbolKind::Enum
1043 | SyntaxKind::UNION 1046 | SymbolKind::Union
1044 ) 1047 )
1045 }) 1048 })
1046 .map(|it| { 1049 .map(|it| {
@@ -1263,7 +1266,7 @@ pub(crate) fn handle_call_hierarchy_prepare(
1263 let RangeInfo { range: _, info: navs } = nav_info; 1266 let RangeInfo { range: _, info: navs } = nav_info;
1264 let res = navs 1267 let res = navs
1265 .into_iter() 1268 .into_iter()
1266 .filter(|it| it.kind == SyntaxKind::FN) 1269 .filter(|it| it.kind == Some(SymbolKind::Function))
1267 .map(|it| to_proto::call_hierarchy_item(&snap, it)) 1270 .map(|it| to_proto::call_hierarchy_item(&snap, it))
1268 .collect::<Result<Vec<_>>>()?; 1271 .collect::<Result<Vec<_>>>()?;
1269 1272
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 715f8927a..e0561b5a7 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -5,14 +5,13 @@ use std::{
5}; 5};
6 6
7use ide::{ 7use ide::{
8 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, 8 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId,
9 FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange, 9 FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag,
10 Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, 10 HighlightedRange, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup,
11 ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, 11 NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange,
12 SourceFileEdit, SymbolKind, TextEdit, TextRange, TextSize,
12}; 13};
13use ide_db::base_db::{FileId, FileRange};
14use itertools::Itertools; 14use itertools::Itertools;
15use syntax::{SyntaxKind, TextRange, TextSize};
16 15
17use crate::{ 16use crate::{
18 cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, 17 cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot,
@@ -30,21 +29,25 @@ pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Rang
30 lsp_types::Range::new(start, end) 29 lsp_types::Range::new(start, end)
31} 30}
32 31
33pub(crate) fn symbol_kind(syntax_kind: SyntaxKind) -> lsp_types::SymbolKind { 32pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
34 match syntax_kind { 33 match symbol_kind {
35 SyntaxKind::FN => lsp_types::SymbolKind::Function, 34 SymbolKind::Function => lsp_types::SymbolKind::Function,
36 SyntaxKind::STRUCT => lsp_types::SymbolKind::Struct, 35 SymbolKind::Struct => lsp_types::SymbolKind::Struct,
37 SyntaxKind::ENUM => lsp_types::SymbolKind::Enum, 36 SymbolKind::Enum => lsp_types::SymbolKind::Enum,
38 SyntaxKind::VARIANT => lsp_types::SymbolKind::EnumMember, 37 SymbolKind::Variant => lsp_types::SymbolKind::EnumMember,
39 SyntaxKind::TRAIT => lsp_types::SymbolKind::Interface, 38 SymbolKind::Trait => lsp_types::SymbolKind::Interface,
40 SyntaxKind::MACRO_CALL => lsp_types::SymbolKind::Function, 39 SymbolKind::Macro => lsp_types::SymbolKind::Function,
41 SyntaxKind::MODULE => lsp_types::SymbolKind::Module, 40 SymbolKind::Module => lsp_types::SymbolKind::Module,
42 SyntaxKind::TYPE_ALIAS => lsp_types::SymbolKind::TypeParameter, 41 SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TypeParameter,
43 SyntaxKind::RECORD_FIELD => lsp_types::SymbolKind::Field, 42 SymbolKind::Field => lsp_types::SymbolKind::Field,
44 SyntaxKind::STATIC => lsp_types::SymbolKind::Constant, 43 SymbolKind::Static => lsp_types::SymbolKind::Constant,
45 SyntaxKind::CONST => lsp_types::SymbolKind::Constant, 44 SymbolKind::Const => lsp_types::SymbolKind::Constant,
46 SyntaxKind::IMPL => lsp_types::SymbolKind::Object, 45 SymbolKind::Impl => lsp_types::SymbolKind::Object,
47 _ => lsp_types::SymbolKind::Variable, 46 SymbolKind::Local
47 | SymbolKind::SelfParam
48 | SymbolKind::LifetimeParam
49 | SymbolKind::ValueParam => lsp_types::SymbolKind::Variable,
50 SymbolKind::Union => lsp_types::SymbolKind::Struct,
48 } 51 }
49} 52}
50 53
@@ -369,34 +372,41 @@ fn semantic_token_type_and_modifiers(
369) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { 372) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) {
370 let mut mods = semantic_tokens::ModifierSet::default(); 373 let mut mods = semantic_tokens::ModifierSet::default();
371 let type_ = match highlight.tag { 374 let type_ = match highlight.tag {
372 HighlightTag::Struct => lsp_types::SemanticTokenType::STRUCT, 375 HighlightTag::Symbol(symbol) => match symbol {
373 HighlightTag::Enum => lsp_types::SemanticTokenType::ENUM, 376 SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
374 HighlightTag::Union => semantic_tokens::UNION, 377 SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE,
375 HighlightTag::TypeAlias => semantic_tokens::TYPE_ALIAS, 378 SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
376 HighlightTag::Trait => lsp_types::SemanticTokenType::INTERFACE, 379 SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
380 SymbolKind::LifetimeParam => semantic_tokens::LIFETIME,
381 SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
382 SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD,
383 SymbolKind::Local => lsp_types::SemanticTokenType::VARIABLE,
384 SymbolKind::Function => {
385 if highlight.modifiers.contains(HighlightModifier::Associated) {
386 lsp_types::SemanticTokenType::METHOD
387 } else {
388 lsp_types::SemanticTokenType::FUNCTION
389 }
390 }
391 SymbolKind::Const => {
392 mods |= semantic_tokens::CONSTANT;
393 mods |= lsp_types::SemanticTokenModifier::STATIC;
394 lsp_types::SemanticTokenType::VARIABLE
395 }
396 SymbolKind::Static => {
397 mods |= lsp_types::SemanticTokenModifier::STATIC;
398 lsp_types::SemanticTokenType::VARIABLE
399 }
400 SymbolKind::Struct => lsp_types::SemanticTokenType::STRUCT,
401 SymbolKind::Enum => lsp_types::SemanticTokenType::ENUM,
402 SymbolKind::Variant => lsp_types::SemanticTokenType::ENUM_MEMBER,
403 SymbolKind::Union => semantic_tokens::UNION,
404 SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS,
405 SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE,
406 SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO,
407 },
377 HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE, 408 HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
378 HighlightTag::SelfKeyword => semantic_tokens::SELF_KEYWORD, 409 HighlightTag::Dummy => semantic_tokens::GENERIC,
379 HighlightTag::SelfType => lsp_types::SemanticTokenType::TYPE,
380 HighlightTag::Field => lsp_types::SemanticTokenType::PROPERTY,
381 HighlightTag::Function => lsp_types::SemanticTokenType::FUNCTION,
382 HighlightTag::Generic => semantic_tokens::GENERIC,
383 HighlightTag::Module => lsp_types::SemanticTokenType::NAMESPACE,
384 HighlightTag::Method => lsp_types::SemanticTokenType::METHOD,
385 HighlightTag::Constant => {
386 mods |= semantic_tokens::CONSTANT;
387 mods |= lsp_types::SemanticTokenModifier::STATIC;
388 lsp_types::SemanticTokenType::VARIABLE
389 }
390 HighlightTag::Static => {
391 mods |= lsp_types::SemanticTokenModifier::STATIC;
392 lsp_types::SemanticTokenType::VARIABLE
393 }
394 HighlightTag::EnumVariant => lsp_types::SemanticTokenType::ENUM_MEMBER,
395 HighlightTag::Macro => lsp_types::SemanticTokenType::MACRO,
396 HighlightTag::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
397 HighlightTag::Local => lsp_types::SemanticTokenType::VARIABLE,
398 HighlightTag::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
399 HighlightTag::Lifetime => semantic_tokens::LIFETIME,
400 HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => { 410 HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => {
401 lsp_types::SemanticTokenType::NUMBER 411 lsp_types::SemanticTokenType::NUMBER
402 } 412 }
@@ -426,6 +436,7 @@ fn semantic_token_type_and_modifiers(
426 HighlightModifier::Unsafe => semantic_tokens::UNSAFE, 436 HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
427 HighlightModifier::Callable => semantic_tokens::CALLABLE, 437 HighlightModifier::Callable => semantic_tokens::CALLABLE,
428 HighlightModifier::Static => lsp_types::SemanticTokenModifier::STATIC, 438 HighlightModifier::Static => lsp_types::SemanticTokenModifier::STATIC,
439 HighlightModifier::Associated => continue,
429 }; 440 };
430 mods |= modifier; 441 mods |= modifier;
431 } 442 }
@@ -633,7 +644,7 @@ pub(crate) fn resource_op(
633 lsp_types::ResourceOp::Create(lsp_types::CreateFile { 644 lsp_types::ResourceOp::Create(lsp_types::CreateFile {
634 uri, 645 uri,
635 options: None, 646 options: None,
636 annotation: None, 647 annotation_id: None,
637 }) 648 })
638 } 649 }
639 FileSystemEdit::MoveFile { src, dst } => { 650 FileSystemEdit::MoveFile { src, dst } => {
@@ -643,7 +654,7 @@ pub(crate) fn resource_op(
643 old_uri, 654 old_uri,
644 new_uri, 655 new_uri,
645 options: None, 656 options: None,
646 annotation: None, 657 annotation_id: None,
647 }) 658 })
648 } 659 }
649 } 660 }
@@ -708,6 +719,7 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
708 .collect(), 719 .collect(),
709 ) 720 )
710 }), 721 }),
722 change_annotations: None,
711 } 723 }
712 } 724 }
713} 725}
@@ -718,7 +730,7 @@ pub(crate) fn call_hierarchy_item(
718) -> Result<lsp_types::CallHierarchyItem> { 730) -> Result<lsp_types::CallHierarchyItem> {
719 let name = target.name.to_string(); 731 let name = target.name.to_string();
720 let detail = target.description.clone(); 732 let detail = target.description.clone();
721 let kind = symbol_kind(target.kind); 733 let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::Function);
722 let (uri, range, selection_range) = location_info(snap, target)?; 734 let (uri, range, selection_range) = location_info(snap, target)?;
723 Ok(lsp_types::CallHierarchyItem { 735 Ok(lsp_types::CallHierarchyItem {
724 name, 736 name,
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 16b079c42..ba7e5d2fb 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -20,6 +20,9 @@ pub fn name_ref(text: &str) -> ast::NameRef {
20pub fn ty(text: &str) -> ast::Type { 20pub fn ty(text: &str) -> ast::Type {
21 ast_from_text(&format!("impl {} for D {{}};", text)) 21 ast_from_text(&format!("impl {} for D {{}};", text))
22} 22}
23pub fn ty_unit() -> ast::Type {
24 ty("()")
25}
23 26
24pub fn assoc_item_list() -> ast::AssocItemList { 27pub fn assoc_item_list() -> ast::AssocItemList {
25 ast_from_text("impl C for D {};") 28 ast_from_text("impl C for D {};")
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index e753b11bb..4d272f367 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -205,6 +205,13 @@ impl ast::Type {
205 } 205 }
206} 206}
207 207
208impl ast::Attr {
209 /// Returns `text`, parsed as an attribute, but only if it has no errors.
210 pub fn parse(text: &str) -> Result<Self, ()> {
211 parsing::parse_text_fragment(text, parser::FragmentKind::Attr)
212 }
213}
214
208/// Matches a `SyntaxNode` against an `ast` type. 215/// Matches a `SyntaxNode` against an `ast` type.
209/// 216///
210/// # Example: 217/// # Example: