aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock24
-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
-rw-r--r--editors/code/package-lock.json71
-rw-r--r--editors/code/package.json6
-rw-r--r--editors/code/src/main.ts11
85 files changed, 1760 insertions, 1548 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4476d188b..1051c4ec6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -26,9 +26,9 @@ dependencies = [
26 26
27[[package]] 27[[package]]
28name = "anyhow" 28name = "anyhow"
29version = "1.0.35" 29version = "1.0.36"
30source = "registry+https://github.com/rust-lang/crates.io-index" 30source = "registry+https://github.com/rust-lang/crates.io-index"
31checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4" 31checksum = "68803225a7b13e47191bab76f2687382b60d259e8cf37f6e1893658b84bb9479"
32 32
33[[package]] 33[[package]]
34name = "anymap" 34name = "anymap"
@@ -685,9 +685,9 @@ dependencies = [
685 685
686[[package]] 686[[package]]
687name = "indexmap" 687name = "indexmap"
688version = "1.6.0" 688version = "1.6.1"
689source = "registry+https://github.com/rust-lang/crates.io-index" 689source = "registry+https://github.com/rust-lang/crates.io-index"
690checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" 690checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
691dependencies = [ 691dependencies = [
692 "autocfg", 692 "autocfg",
693 "hashbrown", 693 "hashbrown",
@@ -844,9 +844,9 @@ dependencies = [
844 844
845[[package]] 845[[package]]
846name = "lsp-types" 846name = "lsp-types"
847version = "0.85.0" 847version = "0.86.0"
848source = "registry+https://github.com/rust-lang/crates.io-index" 848source = "registry+https://github.com/rust-lang/crates.io-index"
849checksum = "857650f3e83fb62f89d15410414e0ed7d0735445020da398d37f65d20a5423b9" 849checksum = "f2a5c40d566f2704dac30859bca152217583fc94fd5b178d8baba915e1abd382"
850dependencies = [ 850dependencies = [
851 "base64", 851 "base64",
852 "bitflags", 852 "bitflags",
@@ -1105,9 +1105,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
1105 1105
1106[[package]] 1106[[package]]
1107name = "perf-event" 1107name = "perf-event"
1108version = "0.4.5" 1108version = "0.4.6"
1109source = "registry+https://github.com/rust-lang/crates.io-index" 1109source = "registry+https://github.com/rust-lang/crates.io-index"
1110checksum = "273069d0b956939ba75e8b5663328b9b7f0dc2e262b3306c6be66c4d87e2240a" 1110checksum = "b7a1c2678a77d65edf773bd900f5b87f0944ac3421949842a2c6a4efe42d6c66"
1111dependencies = [ 1111dependencies = [
1112 "libc", 1112 "libc",
1113 "perf-event-open-sys", 1113 "perf-event-open-sys",
@@ -1990,18 +1990,18 @@ dependencies = [
1990 1990
1991[[package]] 1991[[package]]
1992name = "xshell" 1992name = "xshell"
1993version = "0.1.7" 1993version = "0.1.8"
1994source = "registry+https://github.com/rust-lang/crates.io-index" 1994source = "registry+https://github.com/rust-lang/crates.io-index"
1995checksum = "ed0728d188f2ae530490b7d92435728aba53c6aed06d07e1951da9bd4c1d0798" 1995checksum = "ed373ede30cea03e8c0af22f48ee1ba80efbf06fec8b4746977e6ee703878de0"
1996dependencies = [ 1996dependencies = [
1997 "xshell-macros", 1997 "xshell-macros",
1998] 1998]
1999 1999
2000[[package]] 2000[[package]]
2001name = "xshell-macros" 2001name = "xshell-macros"
2002version = "0.1.7" 2002version = "0.1.8"
2003source = "registry+https://github.com/rust-lang/crates.io-index" 2003source = "registry+https://github.com/rust-lang/crates.io-index"
2004checksum = "367f903cc3f8bc4f4b2400d47dfa6c9e3e121ffb51a30cf0fb67a72c0a0f9617" 2004checksum = "7f6af9f8119104697b0105989a73c578ce33f922d9d6f3dae0e8ae3d538db321"
2005 2005
2006[[package]] 2006[[package]]
2007name = "xtask" 2007name = "xtask"
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 {