aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assists/add_import.rs2
-rw-r--r--crates/ra_hir/src/code_model.rs80
-rw-r--r--crates/ra_hir/src/from_source.rs80
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/source_binder.rs8
-rw-r--r--crates/ra_hir_def/Cargo.toml1
-rw-r--r--crates/ra_hir_def/src/body.rs63
-rw-r--r--crates/ra_hir_def/src/body/lower.rs57
-rw-r--r--crates/ra_hir_def/src/child_by_source.rs97
-rw-r--r--crates/ra_hir_def/src/data.rs12
-rw-r--r--crates/ra_hir_def/src/lib.rs283
-rw-r--r--crates/ra_hir_def/src/marks.rs1
-rw-r--r--crates/ra_hir_def/src/nameres.rs11
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs20
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs21
-rw-r--r--crates/ra_hir_def/src/path.rs41
-rw-r--r--crates/ra_hir_def/src/path/lower.rs6
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs12
-rw-r--r--crates/ra_hir_def/src/resolver.rs19
-rw-r--r--crates/ra_hir_def/src/src.rs82
-rw-r--r--crates/ra_hir_ty/src/display.rs12
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs12
-rw-r--r--crates/ra_hir_ty/src/lib.rs41
-rw-r--r--crates/ra_hir_ty/src/lower.rs10
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs12
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs12
-rw-r--r--crates/ra_hir_ty/src/utils.rs8
-rw-r--r--crates/ra_ide/src/call_info.rs43
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs15
-rw-r--r--crates/ra_ide/src/goto_definition.rs243
-rw-r--r--crates/ra_ide/src/hover.rs19
-rw-r--r--crates/ra_ide/src/inlay_hints.rs26
-rw-r--r--crates/ra_ide/src/marks.rs9
-rw-r--r--crates/ra_ide/src/references/classify.rs9
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html4
-rw-r--r--crates/ra_ide/src/snapshots/rainbow_highlighting.html1
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs11
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs14
-rw-r--r--crates/ra_mbe/src/tests.rs669
-rw-r--r--crates/ra_parser/src/grammar.rs2
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs3
-rw-r--r--crates/ra_parser/src/lib.rs1
-rw-r--r--crates/ra_parser/src/parser.rs2
-rw-r--r--crates/ra_parser/src/token_set.rs8
-rw-r--r--crates/test_utils/src/lib.rs4
47 files changed, 1050 insertions, 1047 deletions
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs
index ceffee9b8..b8752cbad 100644
--- a/crates/ra_assists/src/assists/add_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -590,7 +590,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
590 } 590 }
591 ps.push(chain.into()); 591 ps.push(chain.into());
592 } 592 }
593 hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, 593 hir::PathKind::DollarCrate(_) => return None,
594 } 594 }
595 ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); 595 ps.extend(path.segments().iter().map(|it| it.name.to_string().into()));
596 Some(ps) 596 Some(ps)
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 7850ea9a7..ecf883272 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -11,9 +11,9 @@ use hir_def::{
11 per_ns::PerNs, 11 per_ns::PerNs,
12 resolver::HasResolver, 12 resolver::HasResolver,
13 type_ref::{Mutability, TypeRef}, 13 type_ref::{Mutability, TypeRef},
14 AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, 14 AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId,
15 LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, 15 LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId,
16 StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, 16 TraitId, TypeAliasId, TypeParamId, UnionId,
17}; 17};
18use hir_expand::{ 18use hir_expand::{
19 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -269,7 +269,7 @@ pub struct Struct {
269 269
270impl Struct { 270impl Struct {
271 pub fn module(self, db: &impl DefDatabase) -> Module { 271 pub fn module(self, db: &impl DefDatabase) -> Module {
272 Module { id: self.id.lookup(db).container } 272 Module { id: self.id.lookup(db).container.module(db) }
273 } 273 }
274 274
275 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 275 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -290,7 +290,7 @@ impl Struct {
290 } 290 }
291 291
292 pub fn ty(self, db: &impl HirDatabase) -> Type { 292 pub fn ty(self, db: &impl HirDatabase) -> Type {
293 Type::from_def(db, self.id.lookup(db).container.krate, self.id) 293 Type::from_def(db, self.id.lookup(db).container.module(db).krate, self.id)
294 } 294 }
295 295
296 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 296 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
@@ -309,11 +309,11 @@ impl Union {
309 } 309 }
310 310
311 pub fn module(self, db: &impl DefDatabase) -> Module { 311 pub fn module(self, db: &impl DefDatabase) -> Module {
312 Module { id: self.id.lookup(db).container } 312 Module { id: self.id.lookup(db).container.module(db) }
313 } 313 }
314 314
315 pub fn ty(self, db: &impl HirDatabase) -> Type { 315 pub fn ty(self, db: &impl HirDatabase) -> Type {
316 Type::from_def(db, self.id.lookup(db).container.krate, self.id) 316 Type::from_def(db, self.id.lookup(db).container.module(db).krate, self.id)
317 } 317 }
318 318
319 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 319 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
@@ -337,7 +337,7 @@ pub struct Enum {
337 337
338impl Enum { 338impl Enum {
339 pub fn module(self, db: &impl DefDatabase) -> Module { 339 pub fn module(self, db: &impl DefDatabase) -> Module {
340 Module { id: self.id.lookup(db).container } 340 Module { id: self.id.lookup(db).container.module(db) }
341 } 341 }
342 342
343 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 343 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -357,7 +357,7 @@ impl Enum {
357 } 357 }
358 358
359 pub fn ty(self, db: &impl HirDatabase) -> Type { 359 pub fn ty(self, db: &impl HirDatabase) -> Type {
360 Type::from_def(db, self.id.lookup(db).container.krate, self.id) 360 Type::from_def(db, self.id.lookup(db).container.module(db).krate, self.id)
361 } 361 }
362} 362}
363 363
@@ -529,30 +529,6 @@ impl Const {
529 pub fn name(self, db: &impl HirDatabase) -> Option<Name> { 529 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
530 db.const_data(self.id).name.clone() 530 db.const_data(self.id).name.clone()
531 } 531 }
532
533 /// The containing impl block, if this is a type alias.
534 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
535 match self.container(db) {
536 Some(Container::ImplBlock(it)) => Some(it),
537 _ => None,
538 }
539 }
540
541 /// The containing trait, if this is a trait type alias definition.
542 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
543 match self.container(db) {
544 Some(Container::Trait(it)) => Some(it),
545 _ => None,
546 }
547 }
548
549 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
550 match self.id.lookup(db).container {
551 ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
552 ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
553 ContainerId::ModuleId(_) => None,
554 }
555 }
556} 532}
557 533
558#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 534#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -577,7 +553,7 @@ pub struct Trait {
577 553
578impl Trait { 554impl Trait {
579 pub fn module(self, db: &impl DefDatabase) -> Module { 555 pub fn module(self, db: &impl DefDatabase) -> Module {
580 Module { id: self.id.lookup(db).container } 556 Module { id: self.id.lookup(db).container.module(db) }
581 } 557 }
582 558
583 pub fn name(self, db: &impl DefDatabase) -> Name { 559 pub fn name(self, db: &impl DefDatabase) -> Name {
@@ -612,30 +588,6 @@ impl TypeAlias {
612 Some(self.module(db).krate()) 588 Some(self.module(db).krate())
613 } 589 }
614 590
615 /// The containing impl block, if this is a type alias.
616 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
617 match self.container(db) {
618 Some(Container::ImplBlock(it)) => Some(it),
619 _ => None,
620 }
621 }
622
623 /// The containing trait, if this is a trait type alias definition.
624 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
625 match self.container(db) {
626 Some(Container::Trait(it)) => Some(it),
627 _ => None,
628 }
629 }
630
631 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
632 match self.id.lookup(db).container {
633 ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
634 ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
635 ContainerId::ModuleId(_) => None,
636 }
637 }
638
639 pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> { 591 pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> {
640 db.type_alias_data(self.id).type_ref.clone() 592 db.type_alias_data(self.id).type_ref.clone()
641 } 593 }
@@ -654,14 +606,6 @@ pub struct MacroDef {
654 pub(crate) id: MacroDefId, 606 pub(crate) id: MacroDefId,
655} 607}
656 608
657impl MacroDef {}
658
659pub enum Container {
660 Trait(Trait),
661 ImplBlock(ImplBlock),
662}
663impl_froms!(Container: Trait, ImplBlock);
664
665#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 609#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
666pub enum AssocItem { 610pub enum AssocItem {
667 Function(Function), 611 Function(Function),
@@ -810,7 +754,7 @@ impl ImplBlock {
810 let environment = TraitEnvironment::lower(db, &resolver); 754 let environment = TraitEnvironment::lower(db, &resolver);
811 let ty = Ty::from_hir(db, &resolver, &impl_data.target_type); 755 let ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
812 Type { 756 Type {
813 krate: self.id.lookup(db).container.krate, 757 krate: self.id.lookup(db).container.module(db).krate,
814 ty: InEnvironment { value: ty, environment }, 758 ty: InEnvironment { value: ty, environment },
815 } 759 }
816 } 760 }
@@ -824,7 +768,7 @@ impl ImplBlock {
824 } 768 }
825 769
826 pub fn module(&self, db: &impl DefDatabase) -> Module { 770 pub fn module(&self, db: &impl DefDatabase) -> Module {
827 self.id.lookup(db).container.into() 771 self.id.lookup(db).container.module(db).into()
828 } 772 }
829 773
830 pub fn krate(&self, db: &impl DefDatabase) -> Crate { 774 pub fn krate(&self, db: &impl DefDatabase) -> Crate {
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 7abb4bd75..42ca55fe7 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,8 +1,10 @@
1//! FIXME: write short doc here 1//! Finds a corresponding hir data structure for a syntax node in a specific
2//! file.
3
2use hir_def::{ 4use hir_def::{
3 child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, 5 child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource,
4 ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId, 6 ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId,
5 TraitId, TypeAliasId, UnionId, VariantId, 7 StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
6}; 8};
7use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 9use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
8use ra_syntax::{ 10use ra_syntax::{
@@ -11,14 +13,14 @@ use ra_syntax::{
11}; 13};
12 14
13use crate::{ 15use crate::{
14 db::{AstDatabase, DefDatabase, HirDatabase}, 16 db::{DefDatabase, HirDatabase},
15 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, 17 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local,
16 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, 18 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
17}; 19};
18 20
19pub trait FromSource: Sized { 21pub trait FromSource: Sized {
20 type Ast; 22 type Ast;
21 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self>; 23 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>;
22} 24}
23 25
24pub trait FromSourceByContainer: Sized { 26pub trait FromSourceByContainer: Sized {
@@ -32,7 +34,7 @@ where
32 T: From<<T as FromSourceByContainer>::Id>, 34 T: From<<T as FromSourceByContainer>::Id>,
33{ 35{
34 type Ast = <T as FromSourceByContainer>::Ast; 36 type Ast = <T as FromSourceByContainer>::Ast;
35 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 37 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
36 analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY] 38 analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY]
37 .get(&src) 39 .get(&src)
38 .copied() 40 .copied()
@@ -64,7 +66,7 @@ from_source_by_container_impls![
64 66
65impl FromSource for MacroDef { 67impl FromSource for MacroDef {
66 type Ast = ast::MacroCall; 68 type Ast = ast::MacroCall;
67 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 69 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
68 let kind = MacroDefKind::Declarative; 70 let kind = MacroDefKind::Declarative;
69 71
70 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 72 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
@@ -80,7 +82,7 @@ impl FromSource for MacroDef {
80 82
81impl FromSource for EnumVariant { 83impl FromSource for EnumVariant {
82 type Ast = ast::EnumVariant; 84 type Ast = ast::EnumVariant;
83 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 85 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
84 let parent_enum = src.value.parent_enum(); 86 let parent_enum = src.value.parent_enum();
85 let src_enum = InFile { file_id: src.file_id, value: parent_enum }; 87 let src_enum = InFile { file_id: src.file_id, value: parent_enum };
86 let parent_enum = Enum::from_source(db, src_enum)?; 88 let parent_enum = Enum::from_source(db, src_enum)?;
@@ -93,7 +95,7 @@ impl FromSource for EnumVariant {
93 95
94impl FromSource for StructField { 96impl FromSource for StructField {
95 type Ast = FieldSource; 97 type Ast = FieldSource;
96 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 98 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> {
97 let src = src.as_ref(); 99 let src = src.as_ref();
98 100
99 // FIXME this is buggy 101 // FIXME this is buggy
@@ -212,29 +214,43 @@ impl Module {
212} 214}
213 215
214fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { 216fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap {
215 _analyze_container(db, src).unwrap_or_default() 217 return child_by_source(db, src).unwrap_or_default();
216}
217 218
218fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<DynMap> { 219 fn child_by_source(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<DynMap> {
219 // FIXME: this doesn't try to handle nested declarations 220 for container in src.value.ancestors().skip(1) {
220 for container in src.value.ancestors().skip(1) { 221 let res = match_ast! {
221 let res = match_ast! { 222 match container {
222 match container { 223 ast::TraitDef(it) => {
223 ast::TraitDef(it) => { 224 let def = Trait::from_source(db, src.with_value(it))?;
224 let c = Trait::from_source(db, src.with_value(it))?; 225 def.id.child_by_source(db)
225 c.id.child_by_source(db) 226 },
226 }, 227 ast::ImplBlock(it) => {
227 ast::ImplBlock(it) => { 228 let def = ImplBlock::from_source(db, src.with_value(it))?;
228 let c = ImplBlock::from_source(db, src.with_value(it))?; 229 def.id.child_by_source(db)
229 c.id.child_by_source(db) 230 },
230 }, 231 ast::FnDef(it) => {
231 _ => { continue }, 232 let def = Function::from_source(db, src.with_value(it))?;
232 } 233 DefWithBodyId::from(def.id)
233 }; 234 .child_by_source(db)
234 return Some(res); 235 },
235 } 236 ast::StaticDef(it) => {
237 let def = Static::from_source(db, src.with_value(it))?;
238 DefWithBodyId::from(def.id)
239 .child_by_source(db)
240 },
241 ast::ConstDef(it) => {
242 let def = Const::from_source(db, src.with_value(it))?;
243 DefWithBodyId::from(def.id)
244 .child_by_source(db)
245 },
246 _ => { continue },
247 }
248 };
249 return Some(res);
250 }
236 251
237 let module_source = ModuleSource::from_child_node(db, src); 252 let module_source = ModuleSource::from_child_node(db, src);
238 let c = Module::from_definition(db, src.with_value(module_source))?; 253 let c = Module::from_definition(db, src.with_value(module_source))?;
239 Some(c.id.child_by_source(db)) 254 Some(c.id.child_by_source(db))
255 }
240} 256}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 2e52a1f5c..7f9aef770 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -39,7 +39,7 @@ mod from_source;
39 39
40pub use crate::{ 40pub use crate::{
41 code_model::{ 41 code_model::{
42 Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum, 42 Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum,
43 EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, 43 EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local,
44 MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, 44 MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias,
45 TypeParam, Union, VariantDef, 45 TypeParam, Union, VariantDef,
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index d326169b3..b60a6b87e 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -237,7 +237,13 @@ impl SourceAnalyzer {
237 } 237 }
238 238
239 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> { 239 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> {
240 let expr_id = self.expr_id(&field.expr()?)?; 240 let expr_id = match field.expr() {
241 Some(it) => self.expr_id(&it)?,
242 None => {
243 let src = InFile { file_id: self.file_id, value: field };
244 self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?
245 }
246 };
241 self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) 247 self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into())
242 } 248 }
243 249
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml
index b1923bbf2..2c368f690 100644
--- a/crates/ra_hir_def/Cargo.toml
+++ b/crates/ra_hir_def/Cargo.toml
@@ -13,6 +13,7 @@ once_cell = "1.0.1"
13rustc-hash = "1.0" 13rustc-hash = "1.0"
14either = "1.5" 14either = "1.5"
15anymap = "0.12" 15anymap = "0.12"
16drop_bomb = "0.1.4"
16 17
17ra_arena = { path = "../ra_arena" } 18ra_arena = { path = "../ra_arena" }
18ra_db = { path = "../ra_db" } 19ra_db = { path = "../ra_db" }
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 7787cb87f..401fe0b9b 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,10 +3,13 @@
3mod lower; 3mod lower;
4pub mod scope; 4pub mod scope;
5 5
6use std::{ops::Index, sync::Arc}; 6use std::{mem, ops::Index, sync::Arc};
7 7
8use drop_bomb::DropBomb;
8use either::Either; 9use either::Either;
9use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; 10use hir_expand::{
11 ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
12};
10use ra_arena::{map::ArenaMap, Arena}; 13use ra_arena::{map::ArenaMap, Arena};
11use ra_syntax::{ast, AstNode, AstPtr}; 14use ra_syntax::{ast, AstNode, AstPtr};
12use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
@@ -15,15 +18,16 @@ use crate::{
15 db::DefDatabase, 18 db::DefDatabase,
16 expr::{Expr, ExprId, Pat, PatId}, 19 expr::{Expr, ExprId, Pat, PatId},
17 nameres::{BuiltinShadowMode, CrateDefMap}, 20 nameres::{BuiltinShadowMode, CrateDefMap},
18 path::Path, 21 path::{ModPath, Path},
19 src::HasSource, 22 src::HasSource,
20 DefWithBodyId, HasModule, Lookup, ModuleId, 23 DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
21}; 24};
22 25
23struct Expander { 26struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 27 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 28 current_file_id: HirFileId,
26 hygiene: Hygiene, 29 hygiene: Hygiene,
30 ast_id_map: Arc<AstIdMap>,
27 module: ModuleId, 31 module: ModuleId,
28} 32}
29 33
@@ -31,7 +35,8 @@ impl Expander {
31 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 35 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 36 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 37 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 38 let ast_id_map = db.ast_id_map(current_file_id);
39 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
35 } 40 }
36 41
37 fn enter_expand( 42 fn enter_expand(
@@ -44,7 +49,7 @@ impl Expander {
44 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 49 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
45 ); 50 );
46 51
47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 52 if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) {
48 if let Some(def) = self.resolve_path_as_macro(db, &path) { 53 if let Some(def) = self.resolve_path_as_macro(db, &path) {
49 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); 54 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
50 let file_id = call_id.as_file(); 55 let file_id = call_id.as_file();
@@ -52,9 +57,14 @@ impl Expander {
52 if let Some(expr) = ast::Expr::cast(node) { 57 if let Some(expr) = ast::Expr::cast(node) {
53 log::debug!("macro expansion {:#?}", expr.syntax()); 58 log::debug!("macro expansion {:#?}", expr.syntax());
54 59
55 let mark = Mark { file_id: self.current_file_id }; 60 let mark = Mark {
61 file_id: self.current_file_id,
62 ast_id_map: mem::take(&mut self.ast_id_map),
63 bomb: DropBomb::new("expansion mark dropped"),
64 };
56 self.hygiene = Hygiene::new(db, file_id); 65 self.hygiene = Hygiene::new(db, file_id);
57 self.current_file_id = file_id; 66 self.current_file_id = file_id;
67 self.ast_id_map = db.ast_id_map(file_id);
58 68
59 return Some((mark, expr)); 69 return Some((mark, expr));
60 } 70 }
@@ -67,10 +77,11 @@ impl Expander {
67 None 77 None
68 } 78 }
69 79
70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { 80 fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 81 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 82 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 83 self.ast_id_map = mem::take(&mut mark.ast_id_map);
84 mark.bomb.defuse();
74 } 85 }
75 86
76 fn to_source<T>(&self, value: T) -> InFile<T> { 87 fn to_source<T>(&self, value: T) -> InFile<T> {
@@ -81,24 +92,27 @@ impl Expander {
81 Path::from_src(path, &self.hygiene) 92 Path::from_src(path, &self.hygiene)
82 } 93 }
83 94
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 95 fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> {
96 ModPath::from_src(path, &self.hygiene)
97 }
98
99 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> {
85 self.crate_def_map 100 self.crate_def_map
86 .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other) 101 .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
87 .0 102 .0
88 .take_macros() 103 .take_macros()
89 } 104 }
105
106 fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
107 let file_local_id = self.ast_id_map.ast_id(item);
108 AstId::new(self.current_file_id, file_local_id)
109 }
90} 110}
91 111
92struct Mark { 112struct Mark {
93 file_id: HirFileId, 113 file_id: HirFileId,
94} 114 ast_id_map: Arc<AstIdMap>,
95 115 bomb: DropBomb,
96impl Drop for Mark {
97 fn drop(&mut self) {
98 if !std::thread::panicking() {
99 panic!("dropped mark")
100 }
101 }
102} 116}
103 117
104/// The body of an item (function, const etc.). 118/// The body of an item (function, const etc.).
@@ -115,6 +129,7 @@ pub struct Body {
115 pub params: Vec<PatId>, 129 pub params: Vec<PatId>,
116 /// The `ExprId` of the actual body expression. 130 /// The `ExprId` of the actual body expression.
117 pub body_expr: ExprId, 131 pub body_expr: ExprId,
132 pub defs: Vec<ModuleDefId>,
118} 133}
119 134
120pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 135pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
@@ -169,7 +184,7 @@ impl Body {
169 } 184 }
170 }; 185 };
171 let expander = Expander::new(db, file_id, module); 186 let expander = Expander::new(db, file_id, module);
172 let (body, source_map) = Body::new(db, expander, params, body); 187 let (body, source_map) = Body::new(db, def, expander, params, body);
173 (Arc::new(body), Arc::new(source_map)) 188 (Arc::new(body), Arc::new(source_map))
174 } 189 }
175 190
@@ -179,11 +194,12 @@ impl Body {
179 194
180 fn new( 195 fn new(
181 db: &impl DefDatabase, 196 db: &impl DefDatabase,
197 def: DefWithBodyId,
182 expander: Expander, 198 expander: Expander,
183 params: Option<ast::ParamList>, 199 params: Option<ast::ParamList>,
184 body: Option<ast::Expr>, 200 body: Option<ast::Expr>,
185 ) -> (Body, BodySourceMap) { 201 ) -> (Body, BodySourceMap) {
186 lower::lower(db, expander, params, body) 202 lower::lower(db, def, expander, params, body)
187 } 203 }
188} 204}
189 205
@@ -213,6 +229,11 @@ impl BodySourceMap {
213 self.expr_map.get(&src).cloned() 229 self.expr_map.get(&src).cloned()
214 } 230 }
215 231
232 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
233 let src = node.map(|it| Either::Right(AstPtr::new(it)));
234 self.expr_map.get(&src).cloned()
235 }
236
216 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { 237 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
217 self.pat_map_back.get(pat).copied() 238 self.pat_map_back.get(pat).copied()
218 } 239 }
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 61193b4d8..853e17bae 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,11 +2,12 @@
2//! representation. 2//! representation.
3 3
4use either::Either; 4use either::Either;
5
5use hir_expand::name::{name, AsName, Name}; 6use hir_expand::name::{name, AsName, Name};
6use ra_arena::Arena; 7use ra_arena::Arena;
7use ra_syntax::{ 8use ra_syntax::{
8 ast::{ 9 ast::{
9 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, 10 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
10 TypeAscriptionOwner, 11 TypeAscriptionOwner,
11 }, 12 },
12 AstNode, AstPtr, 13 AstNode, AstPtr,
@@ -24,23 +25,28 @@ use crate::{
24 path::GenericArgs, 25 path::GenericArgs,
25 path::Path, 26 path::Path,
26 type_ref::{Mutability, TypeRef}, 27 type_ref::{Mutability, TypeRef},
28 ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StaticLoc,
29 StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
27}; 30};
28 31
29pub(super) fn lower( 32pub(super) fn lower(
30 db: &impl DefDatabase, 33 db: &impl DefDatabase,
34 def: DefWithBodyId,
31 expander: Expander, 35 expander: Expander,
32 params: Option<ast::ParamList>, 36 params: Option<ast::ParamList>,
33 body: Option<ast::Expr>, 37 body: Option<ast::Expr>,
34) -> (Body, BodySourceMap) { 38) -> (Body, BodySourceMap) {
35 ExprCollector { 39 ExprCollector {
36 expander,
37 db, 40 db,
41 def,
42 expander,
38 source_map: BodySourceMap::default(), 43 source_map: BodySourceMap::default(),
39 body: Body { 44 body: Body {
40 exprs: Arena::default(), 45 exprs: Arena::default(),
41 pats: Arena::default(), 46 pats: Arena::default(),
42 params: Vec::new(), 47 params: Vec::new(),
43 body_expr: ExprId::dummy(), 48 body_expr: ExprId::dummy(),
49 defs: Vec::new(),
44 }, 50 },
45 } 51 }
46 .collect(params, body) 52 .collect(params, body)
@@ -48,6 +54,7 @@ pub(super) fn lower(
48 54
49struct ExprCollector<DB> { 55struct ExprCollector<DB> {
50 db: DB, 56 db: DB,
57 def: DefWithBodyId,
51 expander: Expander, 58 expander: Expander,
52 59
53 body: Body, 60 body: Body,
@@ -466,6 +473,7 @@ where
466 Some(block) => block, 473 Some(block) => block,
467 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), 474 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
468 }; 475 };
476 self.collect_block_items(&block);
469 let statements = block 477 let statements = block
470 .statements() 478 .statements()
471 .map(|s| match s { 479 .map(|s| match s {
@@ -482,6 +490,51 @@ where
482 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 490 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
483 } 491 }
484 492
493 fn collect_block_items(&mut self, block: &ast::Block) {
494 let container = ContainerId::DefWithBodyId(self.def);
495 for item in block.items() {
496 let def: ModuleDefId = match item {
497 ast::ModuleItem::FnDef(def) => {
498 let ast_id = self.expander.ast_id(&def);
499 FunctionLoc { container: container.into(), ast_id }.intern(self.db).into()
500 }
501 ast::ModuleItem::TypeAliasDef(def) => {
502 let ast_id = self.expander.ast_id(&def);
503 TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into()
504 }
505 ast::ModuleItem::ConstDef(def) => {
506 let ast_id = self.expander.ast_id(&def);
507 ConstLoc { container: container.into(), ast_id }.intern(self.db).into()
508 }
509 ast::ModuleItem::StaticDef(def) => {
510 let ast_id = self.expander.ast_id(&def);
511 StaticLoc { container, ast_id }.intern(self.db).into()
512 }
513 ast::ModuleItem::StructDef(def) => {
514 let ast_id = self.expander.ast_id(&def);
515 StructLoc { container, ast_id }.intern(self.db).into()
516 }
517 ast::ModuleItem::EnumDef(def) => {
518 let ast_id = self.expander.ast_id(&def);
519 EnumLoc { container, ast_id }.intern(self.db).into()
520 }
521 ast::ModuleItem::UnionDef(def) => {
522 let ast_id = self.expander.ast_id(&def);
523 UnionLoc { container, ast_id }.intern(self.db).into()
524 }
525 ast::ModuleItem::TraitDef(def) => {
526 let ast_id = self.expander.ast_id(&def);
527 TraitLoc { container, ast_id }.intern(self.db).into()
528 }
529 ast::ModuleItem::ImplBlock(_)
530 | ast::ModuleItem::UseItem(_)
531 | ast::ModuleItem::ExternCrateItem(_)
532 | ast::ModuleItem::Module(_) => continue,
533 };
534 self.body.defs.push(def)
535 }
536 }
537
485 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { 538 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
486 if let Some(block) = expr { 539 if let Some(block) = expr {
487 self.collect_block(block) 540 self.collect_block(block)
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs
index 3c9379b15..f5a65ad40 100644
--- a/crates/ra_hir_def/src/child_by_source.rs
+++ b/crates/ra_hir_def/src/child_by_source.rs
@@ -11,8 +11,8 @@ use crate::{
11 dyn_map::DynMap, 11 dyn_map::DynMap,
12 keys, 12 keys,
13 src::{HasChildSource, HasSource}, 13 src::{HasChildSource, HasSource},
14 AdtId, AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, 14 AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId,
15 StructFieldId, TraitId, VariantId, 15 ModuleId, StructFieldId, TraitId, VariantId,
16}; 16};
17 17
18pub trait ChildBySource { 18pub trait ChildBySource {
@@ -76,47 +76,11 @@ impl ChildBySource for ModuleId {
76 let mut res = DynMap::default(); 76 let mut res = DynMap::default();
77 77
78 let crate_def_map = db.crate_def_map(self.krate); 78 let crate_def_map = db.crate_def_map(self.krate);
79 for item in crate_def_map[self.local_id].scope.declarations() { 79 let module_data = &crate_def_map[self.local_id];
80 match item {
81 ModuleDefId::FunctionId(func) => {
82 let src = func.lookup(db).source(db);
83 res[keys::FUNCTION].insert(src, func)
84 }
85 ModuleDefId::ConstId(konst) => {
86 let src = konst.lookup(db).source(db);
87 res[keys::CONST].insert(src, konst)
88 }
89 ModuleDefId::StaticId(statik) => {
90 let src = statik.lookup(db).source(db);
91 res[keys::STATIC].insert(src, statik)
92 }
93 ModuleDefId::TypeAliasId(ty) => {
94 let src = ty.lookup(db).source(db);
95 res[keys::TYPE_ALIAS].insert(src, ty)
96 }
97 ModuleDefId::TraitId(trait_) => {
98 let src = trait_.lookup(db).source(db);
99 res[keys::TRAIT].insert(src, trait_)
100 }
101 ModuleDefId::AdtId(adt) => match adt {
102 AdtId::StructId(strukt) => {
103 let src = strukt.lookup(db).source(db);
104 res[keys::STRUCT].insert(src, strukt)
105 }
106 AdtId::UnionId(union_) => {
107 let src = union_.lookup(db).source(db);
108 res[keys::UNION].insert(src, union_)
109 }
110 AdtId::EnumId(enum_) => {
111 let src = enum_.lookup(db).source(db);
112 res[keys::ENUM].insert(src, enum_)
113 }
114 },
115 _ => (),
116 }
117 }
118 80
119 for &impl_ in crate_def_map[self.local_id].impls.iter() { 81 module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item));
82
83 for &impl_ in module_data.impls.iter() {
120 let src = impl_.lookup(db).source(db); 84 let src = impl_.lookup(db).source(db);
121 res[keys::IMPL].insert(src, impl_) 85 res[keys::IMPL].insert(src, impl_)
122 } 86 }
@@ -125,6 +89,46 @@ impl ChildBySource for ModuleId {
125 } 89 }
126} 90}
127 91
92fn add_module_def(db: &impl DefDatabase, map: &mut DynMap, item: ModuleDefId) {
93 match item {
94 ModuleDefId::FunctionId(func) => {
95 let src = func.lookup(db).source(db);
96 map[keys::FUNCTION].insert(src, func)
97 }
98 ModuleDefId::ConstId(konst) => {
99 let src = konst.lookup(db).source(db);
100 map[keys::CONST].insert(src, konst)
101 }
102 ModuleDefId::StaticId(statik) => {
103 let src = statik.lookup(db).source(db);
104 map[keys::STATIC].insert(src, statik)
105 }
106 ModuleDefId::TypeAliasId(ty) => {
107 let src = ty.lookup(db).source(db);
108 map[keys::TYPE_ALIAS].insert(src, ty)
109 }
110 ModuleDefId::TraitId(trait_) => {
111 let src = trait_.lookup(db).source(db);
112 map[keys::TRAIT].insert(src, trait_)
113 }
114 ModuleDefId::AdtId(adt) => match adt {
115 AdtId::StructId(strukt) => {
116 let src = strukt.lookup(db).source(db);
117 map[keys::STRUCT].insert(src, strukt)
118 }
119 AdtId::UnionId(union_) => {
120 let src = union_.lookup(db).source(db);
121 map[keys::UNION].insert(src, union_)
122 }
123 AdtId::EnumId(enum_) => {
124 let src = enum_.lookup(db).source(db);
125 map[keys::ENUM].insert(src, enum_)
126 }
127 },
128 _ => (),
129 }
130}
131
128impl ChildBySource for VariantId { 132impl ChildBySource for VariantId {
129 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { 133 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
130 let mut res = DynMap::default(); 134 let mut res = DynMap::default();
@@ -160,3 +164,12 @@ impl ChildBySource for EnumId {
160 res 164 res
161 } 165 }
162} 166}
167
168impl ChildBySource for DefWithBodyId {
169 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
170 let mut res = DynMap::default();
171 let body = db.body(*self);
172 body.defs.iter().copied().for_each(|item| add_module_def(db, &mut res, item));
173 res
174 }
175}
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 4f4ef57cc..14e86936b 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -12,8 +12,8 @@ use crate::{
12 db::DefDatabase, 12 db::DefDatabase,
13 src::HasSource, 13 src::HasSource,
14 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
15 AssocItemId, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, ImplId, Intern, Lookup, 15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, ImplId, Intern,
16 StaticId, TraitId, TypeAliasId, TypeAliasLoc, 16 Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
17}; 17};
18 18
19#[derive(Debug, Clone, PartialEq, Eq)] 19#[derive(Debug, Clone, PartialEq, Eq)]
@@ -99,7 +99,7 @@ impl TraitData {
99 let auto = src.value.is_auto(); 99 let auto = src.value.is_auto();
100 let ast_id_map = db.ast_id_map(src.file_id); 100 let ast_id_map = db.ast_id_map(src.file_id);
101 101
102 let container = ContainerId::TraitId(tr); 102 let container = AssocContainerId::TraitId(tr);
103 let items = if let Some(item_list) = src.value.item_list() { 103 let items = if let Some(item_list) = src.value.item_list() {
104 item_list 104 item_list
105 .impl_items() 105 .impl_items()
@@ -180,7 +180,7 @@ impl ImplData {
180 .map(|item_node| match item_node { 180 .map(|item_node| match item_node {
181 ast::ImplItem::FnDef(it) => { 181 ast::ImplItem::FnDef(it) => {
182 let def = FunctionLoc { 182 let def = FunctionLoc {
183 container: ContainerId::ImplId(id), 183 container: AssocContainerId::ImplId(id),
184 ast_id: AstId::new(src.file_id, items.ast_id(&it)), 184 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
185 } 185 }
186 .intern(db); 186 .intern(db);
@@ -188,7 +188,7 @@ impl ImplData {
188 } 188 }
189 ast::ImplItem::ConstDef(it) => { 189 ast::ImplItem::ConstDef(it) => {
190 let def = ConstLoc { 190 let def = ConstLoc {
191 container: ContainerId::ImplId(id), 191 container: AssocContainerId::ImplId(id),
192 ast_id: AstId::new(src.file_id, items.ast_id(&it)), 192 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
193 } 193 }
194 .intern(db); 194 .intern(db);
@@ -196,7 +196,7 @@ impl ImplData {
196 } 196 }
197 ast::ImplItem::TypeAliasDef(it) => { 197 ast::ImplItem::TypeAliasDef(it) => {
198 let def = TypeAliasLoc { 198 let def = TypeAliasLoc {
199 container: ContainerId::ImplId(id), 199 container: AssocContainerId::ImplId(id),
200 ast_id: AstId::new(src.file_id, items.ast_id(&it)), 200 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
201 } 201 }
202 .intern(db); 202 .intern(db);
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index f085bbe87..8ed1599ff 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -45,7 +45,7 @@ use std::hash::Hash;
45use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId}; 45use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId};
46use ra_arena::{impl_arena_id, RawId}; 46use ra_arena::{impl_arena_id, RawId};
47use ra_db::{impl_intern_key, salsa, CrateId}; 47use ra_db::{impl_intern_key, salsa, CrateId};
48use ra_syntax::ast; 48use ra_syntax::{ast, AstNode};
49 49
50use crate::builtin_type::BuiltinType; 50use crate::builtin_type::BuiltinType;
51 51
@@ -65,101 +65,57 @@ pub struct ModuleId {
65pub struct LocalModuleId(RawId); 65pub struct LocalModuleId(RawId);
66impl_arena_id!(LocalModuleId); 66impl_arena_id!(LocalModuleId);
67 67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
69pub struct FunctionId(salsa::InternId);
70impl_intern_key!(FunctionId);
71
72#[derive(Debug, Clone, PartialEq, Eq, Hash)] 68#[derive(Debug, Clone, PartialEq, Eq, Hash)]
73pub struct FunctionLoc { 69pub struct ItemLoc<N: AstNode> {
74 pub container: ContainerId, 70 pub container: ContainerId,
75 pub ast_id: AstId<ast::FnDef>, 71 pub ast_id: AstId<N>,
76} 72}
77 73
78impl Intern for FunctionLoc { 74#[derive(Debug, Clone, PartialEq, Eq, Hash)]
79 type ID = FunctionId; 75pub struct AssocItemLoc<N: AstNode> {
80 fn intern(self, db: &impl db::DefDatabase) -> FunctionId { 76 pub container: AssocContainerId,
81 db.intern_function(self) 77 pub ast_id: AstId<N>,
82 }
83} 78}
84 79
85impl Lookup for FunctionId { 80macro_rules! impl_intern {
86 type Data = FunctionLoc; 81 ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
87 fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc { 82 impl_intern_key!($id);
88 db.lookup_intern_function(*self)
89 }
90}
91 83
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 84 impl Intern for $loc {
93pub struct StructId(salsa::InternId); 85 type ID = $id;
94impl_intern_key!(StructId); 86 fn intern(self, db: &impl db::DefDatabase) -> $id {
87 db.$intern(self)
88 }
89 }
95 90
96#[derive(Debug, Clone, PartialEq, Eq, Hash)] 91 impl Lookup for $id {
97pub struct StructLoc { 92 type Data = $loc;
98 pub container: ModuleId, 93 fn lookup(&self, db: &impl db::DefDatabase) -> $loc {
99 pub ast_id: AstId<ast::StructDef>, 94 db.$lookup(*self)
95 }
96 }
97 };
100} 98}
101 99
102impl Intern for StructLoc { 100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
103 type ID = StructId; 101pub struct FunctionId(salsa::InternId);
104 fn intern(self, db: &impl db::DefDatabase) -> StructId { 102type FunctionLoc = AssocItemLoc<ast::FnDef>;
105 db.intern_struct(self) 103impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
106 }
107}
108 104
109impl Lookup for StructId { 105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
110 type Data = StructLoc; 106pub struct StructId(salsa::InternId);
111 fn lookup(&self, db: &impl db::DefDatabase) -> StructLoc { 107type StructLoc = ItemLoc<ast::StructDef>;
112 db.lookup_intern_struct(*self) 108impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
113 }
114}
115 109
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
117pub struct UnionId(salsa::InternId); 111pub struct UnionId(salsa::InternId);
118impl_intern_key!(UnionId); 112pub type UnionLoc = ItemLoc<ast::UnionDef>;
119 113impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
120#[derive(Debug, Clone, PartialEq, Eq, Hash)]
121pub struct UnionLoc {
122 pub container: ModuleId,
123 pub ast_id: AstId<ast::UnionDef>,
124}
125
126impl Intern for UnionLoc {
127 type ID = UnionId;
128 fn intern(self, db: &impl db::DefDatabase) -> UnionId {
129 db.intern_union(self)
130 }
131}
132
133impl Lookup for UnionId {
134 type Data = UnionLoc;
135 fn lookup(&self, db: &impl db::DefDatabase) -> UnionLoc {
136 db.lookup_intern_union(*self)
137 }
138}
139 114
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
141pub struct EnumId(salsa::InternId); 116pub struct EnumId(salsa::InternId);
142impl_intern_key!(EnumId); 117pub type EnumLoc = ItemLoc<ast::EnumDef>;
143 118impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
145pub struct EnumLoc {
146 pub container: ModuleId,
147 pub ast_id: AstId<ast::EnumDef>,
148}
149
150impl Intern for EnumLoc {
151 type ID = EnumId;
152 fn intern(self, db: &impl db::DefDatabase) -> EnumId {
153 db.intern_enum(self)
154 }
155}
156
157impl Lookup for EnumId {
158 type Data = EnumLoc;
159 fn lookup(&self, db: &impl db::DefDatabase) -> EnumLoc {
160 db.lookup_intern_enum(*self)
161 }
162}
163 119
164// FIXME: rename to `VariantId`, only enums can ave variants 120// FIXME: rename to `VariantId`, only enums can ave variants
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -184,122 +140,38 @@ impl_arena_id!(LocalStructFieldId);
184 140
185#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 141#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186pub struct ConstId(salsa::InternId); 142pub struct ConstId(salsa::InternId);
187impl_intern_key!(ConstId); 143type ConstLoc = AssocItemLoc<ast::ConstDef>;
188#[derive(Debug, Clone, PartialEq, Eq, Hash)] 144impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
189pub struct ConstLoc {
190 pub container: ContainerId,
191 pub ast_id: AstId<ast::ConstDef>,
192}
193
194impl Intern for ConstLoc {
195 type ID = ConstId;
196 fn intern(self, db: &impl db::DefDatabase) -> ConstId {
197 db.intern_const(self)
198 }
199}
200
201impl Lookup for ConstId {
202 type Data = ConstLoc;
203 fn lookup(&self, db: &impl db::DefDatabase) -> ConstLoc {
204 db.lookup_intern_const(*self)
205 }
206}
207 145
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
209pub struct StaticId(salsa::InternId); 147pub struct StaticId(salsa::InternId);
210impl_intern_key!(StaticId); 148pub type StaticLoc = ItemLoc<ast::StaticDef>;
211 149impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
212#[derive(Debug, Clone, PartialEq, Eq, Hash)]
213pub struct StaticLoc {
214 pub container: ModuleId,
215 pub ast_id: AstId<ast::StaticDef>,
216}
217
218impl Intern for StaticLoc {
219 type ID = StaticId;
220 fn intern(self, db: &impl db::DefDatabase) -> StaticId {
221 db.intern_static(self)
222 }
223}
224
225impl Lookup for StaticId {
226 type Data = StaticLoc;
227 fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc {
228 db.lookup_intern_static(*self)
229 }
230}
231 150
232#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 151#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
233pub struct TraitId(salsa::InternId); 152pub struct TraitId(salsa::InternId);
234impl_intern_key!(TraitId); 153pub type TraitLoc = ItemLoc<ast::TraitDef>;
235 154impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
236#[derive(Debug, Clone, PartialEq, Eq, Hash)]
237pub struct TraitLoc {
238 pub container: ModuleId,
239 pub ast_id: AstId<ast::TraitDef>,
240}
241
242impl Intern for TraitLoc {
243 type ID = TraitId;
244 fn intern(self, db: &impl db::DefDatabase) -> TraitId {
245 db.intern_trait(self)
246 }
247}
248
249impl Lookup for TraitId {
250 type Data = TraitLoc;
251 fn lookup(&self, db: &impl db::DefDatabase) -> TraitLoc {
252 db.lookup_intern_trait(*self)
253 }
254}
255 155
256#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
257pub struct TypeAliasId(salsa::InternId); 157pub struct TypeAliasId(salsa::InternId);
258impl_intern_key!(TypeAliasId); 158type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>;
259 159impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
260#[derive(Debug, Clone, PartialEq, Eq, Hash)]
261pub struct TypeAliasLoc {
262 pub container: ContainerId,
263 pub ast_id: AstId<ast::TypeAliasDef>,
264}
265
266impl Intern for TypeAliasLoc {
267 type ID = TypeAliasId;
268 fn intern(self, db: &impl db::DefDatabase) -> TypeAliasId {
269 db.intern_type_alias(self)
270 }
271}
272
273impl Lookup for TypeAliasId {
274 type Data = TypeAliasLoc;
275 fn lookup(&self, db: &impl db::DefDatabase) -> TypeAliasLoc {
276 db.lookup_intern_type_alias(*self)
277 }
278}
279 160
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 161#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
281pub struct ImplId(salsa::InternId); 162pub struct ImplId(salsa::InternId);
282impl_intern_key!(ImplId); 163type ImplLoc = ItemLoc<ast::ImplBlock>;
283 164impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
285pub struct ImplLoc {
286 pub container: ModuleId,
287 pub ast_id: AstId<ast::ImplBlock>,
288}
289 165
290impl Intern for ImplLoc { 166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
291 type ID = ImplId; 167pub struct TypeParamId {
292 fn intern(self, db: &impl db::DefDatabase) -> ImplId { 168 pub parent: GenericDefId,
293 db.intern_impl(self) 169 pub local_id: LocalTypeParamId,
294 }
295} 170}
296 171
297impl Lookup for ImplId { 172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
298 type Data = ImplLoc; 173pub struct LocalTypeParamId(RawId);
299 fn lookup(&self, db: &impl db::DefDatabase) -> ImplLoc { 174impl_arena_id!(LocalTypeParamId);
300 db.lookup_intern_impl(*self)
301 }
302}
303 175
304macro_rules! impl_froms { 176macro_rules! impl_froms {
305 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { 177 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
@@ -321,21 +193,18 @@ macro_rules! impl_froms {
321} 193}
322 194
323#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
324pub struct TypeParamId { 196pub enum ContainerId {
325 pub parent: GenericDefId, 197 ModuleId(ModuleId),
326 pub local_id: LocalTypeParamId, 198 DefWithBodyId(DefWithBodyId),
327} 199}
328 200
329#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 201#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
330pub struct LocalTypeParamId(RawId); 202pub enum AssocContainerId {
331impl_arena_id!(LocalTypeParamId); 203 ContainerId(ContainerId),
332
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
334pub enum ContainerId {
335 ModuleId(ModuleId),
336 ImplId(ImplId), 204 ImplId(ImplId),
337 TraitId(TraitId), 205 TraitId(TraitId),
338} 206}
207impl_froms!(AssocContainerId: ContainerId);
339 208
340/// A Data Type 209/// A Data Type
341#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 210#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -478,33 +347,28 @@ pub trait HasModule {
478 fn module(&self, db: &impl db::DefDatabase) -> ModuleId; 347 fn module(&self, db: &impl db::DefDatabase) -> ModuleId;
479} 348}
480 349
481impl HasModule for FunctionLoc { 350impl HasModule for ContainerId {
482 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 351 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
483 match self.container { 352 match *self {
484 ContainerId::ModuleId(it) => it, 353 ContainerId::ModuleId(it) => it,
485 ContainerId::ImplId(it) => it.lookup(db).container, 354 ContainerId::DefWithBodyId(it) => it.module(db),
486 ContainerId::TraitId(it) => it.lookup(db).container,
487 } 355 }
488 } 356 }
489} 357}
490 358
491impl HasModule for TypeAliasLoc { 359impl HasModule for AssocContainerId {
492 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 360 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
493 match self.container { 361 match *self {
494 ContainerId::ModuleId(it) => it, 362 AssocContainerId::ContainerId(it) => it.module(db),
495 ContainerId::ImplId(it) => it.lookup(db).container, 363 AssocContainerId::ImplId(it) => it.lookup(db).container.module(db),
496 ContainerId::TraitId(it) => it.lookup(db).container, 364 AssocContainerId::TraitId(it) => it.lookup(db).container.module(db),
497 } 365 }
498 } 366 }
499} 367}
500 368
501impl HasModule for ConstLoc { 369impl<N: AstNode> HasModule for AssocItemLoc<N> {
502 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 370 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
503 match self.container { 371 self.container.module(db)
504 ContainerId::ModuleId(it) => it,
505 ContainerId::ImplId(it) => it.lookup(db).container,
506 ContainerId::TraitId(it) => it.lookup(db).container,
507 }
508 } 372 }
509} 373}
510 374
@@ -515,6 +379,7 @@ impl HasModule for AdtId {
515 AdtId::UnionId(it) => it.lookup(db).container, 379 AdtId::UnionId(it) => it.lookup(db).container,
516 AdtId::EnumId(it) => it.lookup(db).container, 380 AdtId::EnumId(it) => it.lookup(db).container,
517 } 381 }
382 .module(db)
518 } 383 }
519} 384}
520 385
@@ -533,17 +398,17 @@ impl HasModule for GenericDefId {
533 match self { 398 match self {
534 GenericDefId::FunctionId(it) => it.lookup(db).module(db), 399 GenericDefId::FunctionId(it) => it.lookup(db).module(db),
535 GenericDefId::AdtId(it) => it.module(db), 400 GenericDefId::AdtId(it) => it.module(db),
536 GenericDefId::TraitId(it) => it.lookup(db).container, 401 GenericDefId::TraitId(it) => it.lookup(db).container.module(db),
537 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), 402 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
538 GenericDefId::ImplId(it) => it.lookup(db).container, 403 GenericDefId::ImplId(it) => it.lookup(db).container.module(db),
539 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, 404 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db),
540 GenericDefId::ConstId(it) => it.lookup(db).module(db), 405 GenericDefId::ConstId(it) => it.lookup(db).module(db),
541 } 406 }
542 } 407 }
543} 408}
544 409
545impl HasModule for StaticLoc { 410impl HasModule for StaticLoc {
546 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { 411 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
547 self.container 412 self.container.module(db)
548 } 413 }
549} 414}
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
index 65239ca0a..457ba4abe 100644
--- a/crates/ra_hir_def/src/marks.rs
+++ b/crates/ra_hir_def/src/marks.rs
@@ -5,6 +5,7 @@ test_utils::marks!(
5 name_res_works_for_broken_modules 5 name_res_works_for_broken_modules
6 can_import_enum_variant 6 can_import_enum_variant
7 glob_enum 7 glob_enum
8 glob_enum_group
8 glob_across_crates 9 glob_across_crates
9 std_prelude 10 std_prelude
10 macro_rules_from_other_crates_are_visible_with_macro_use 11 macro_rules_from_other_crates_are_visible_with_macro_use
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 9aae7e48e..af52fa36e 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -57,9 +57,7 @@ mod tests;
57 57
58use std::sync::Arc; 58use std::sync::Arc;
59 59
60use hir_expand::{ 60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId};
61 ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId,
62};
63use once_cell::sync::Lazy; 61use once_cell::sync::Lazy;
64use ra_arena::Arena; 62use ra_arena::Arena;
65use ra_db::{CrateId, Edition, FileId, FilePosition}; 63use ra_db::{CrateId, Edition, FileId, FilePosition};
@@ -76,7 +74,7 @@ use crate::{
76 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, 74 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
77 path::ModPath, 75 path::ModPath,
78 per_ns::PerNs, 76 per_ns::PerNs,
79 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, 77 AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
80}; 78};
81 79
82/// Contains all top-level defs from a macro-expanded crate 80/// Contains all top-level defs from a macro-expanded crate
@@ -176,11 +174,6 @@ pub struct ModuleData {
176 pub impls: Vec<ImplId>, 174 pub impls: Vec<ImplId>,
177} 175}
178 176
179#[derive(Default, Debug, PartialEq, Eq)]
180pub(crate) struct Declarations {
181 fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>,
182}
183
184#[derive(Debug, Default, PartialEq, Eq)] 177#[derive(Debug, Default, PartialEq, Eq)]
185pub struct ModuleScope { 178pub struct ModuleScope {
186 items: FxHashMap<Name, Resolution>, 179 items: FxHashMap<Name, Resolution>,
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8bbf7ffa2..e68bf4868 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -661,9 +661,10 @@ where
661 krate: self.def_collector.def_map.krate, 661 krate: self.def_collector.def_map.krate,
662 local_id: self.module_id, 662 local_id: self.module_id,
663 }; 663 };
664 let container = ContainerId::ModuleId(module);
664 let ast_id = self.raw_items[imp].ast_id; 665 let ast_id = self.raw_items[imp].ast_id;
665 let impl_id = 666 let impl_id =
666 ImplLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 667 ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
667 .intern(self.def_collector.db); 668 .intern(self.def_collector.db);
668 self.def_collector.def_map.modules[self.module_id].impls.push(impl_id) 669 self.def_collector.def_map.modules[self.module_id].impls.push(impl_id)
669 } 670 }
@@ -760,10 +761,11 @@ where
760 self.collect_derives(attrs, def); 761 self.collect_derives(attrs, def);
761 762
762 let name = def.name.clone(); 763 let name = def.name.clone();
764 let container = ContainerId::ModuleId(module);
763 let def: PerNs = match def.kind { 765 let def: PerNs = match def.kind {
764 raw::DefKind::Function(ast_id) => { 766 raw::DefKind::Function(ast_id) => {
765 let def = FunctionLoc { 767 let def = FunctionLoc {
766 container: ContainerId::ModuleId(module), 768 container: container.into(),
767 ast_id: AstId::new(self.file_id, ast_id), 769 ast_id: AstId::new(self.file_id, ast_id),
768 } 770 }
769 .intern(self.def_collector.db); 771 .intern(self.def_collector.db);
@@ -771,23 +773,23 @@ where
771 PerNs::values(def.into()) 773 PerNs::values(def.into())
772 } 774 }
773 raw::DefKind::Struct(ast_id) => { 775 raw::DefKind::Struct(ast_id) => {
774 let def = StructLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 776 let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
775 .intern(self.def_collector.db); 777 .intern(self.def_collector.db);
776 PerNs::both(def.into(), def.into()) 778 PerNs::both(def.into(), def.into())
777 } 779 }
778 raw::DefKind::Union(ast_id) => { 780 raw::DefKind::Union(ast_id) => {
779 let def = UnionLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 781 let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
780 .intern(self.def_collector.db); 782 .intern(self.def_collector.db);
781 PerNs::both(def.into(), def.into()) 783 PerNs::both(def.into(), def.into())
782 } 784 }
783 raw::DefKind::Enum(ast_id) => { 785 raw::DefKind::Enum(ast_id) => {
784 let def = EnumLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 786 let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
785 .intern(self.def_collector.db); 787 .intern(self.def_collector.db);
786 PerNs::types(def.into()) 788 PerNs::types(def.into())
787 } 789 }
788 raw::DefKind::Const(ast_id) => { 790 raw::DefKind::Const(ast_id) => {
789 let def = ConstLoc { 791 let def = ConstLoc {
790 container: ContainerId::ModuleId(module), 792 container: container.into(),
791 ast_id: AstId::new(self.file_id, ast_id), 793 ast_id: AstId::new(self.file_id, ast_id),
792 } 794 }
793 .intern(self.def_collector.db); 795 .intern(self.def_collector.db);
@@ -795,20 +797,20 @@ where
795 PerNs::values(def.into()) 797 PerNs::values(def.into())
796 } 798 }
797 raw::DefKind::Static(ast_id) => { 799 raw::DefKind::Static(ast_id) => {
798 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 800 let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
799 .intern(self.def_collector.db); 801 .intern(self.def_collector.db);
800 802
801 PerNs::values(def.into()) 803 PerNs::values(def.into())
802 } 804 }
803 raw::DefKind::Trait(ast_id) => { 805 raw::DefKind::Trait(ast_id) => {
804 let def = TraitLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 806 let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
805 .intern(self.def_collector.db); 807 .intern(self.def_collector.db);
806 808
807 PerNs::types(def.into()) 809 PerNs::types(def.into())
808 } 810 }
809 raw::DefKind::TypeAlias(ast_id) => { 811 raw::DefKind::TypeAlias(ast_id) => {
810 let def = TypeAliasLoc { 812 let def = TypeAliasLoc {
811 container: ContainerId::ModuleId(module), 813 container: container.into(),
812 ast_id: AstId::new(self.file_id, ast_id), 814 ast_id: AstId::new(self.file_id, ast_id),
813 } 815 }
814 .intern(self.def_collector.db); 816 .intern(self.def_collector.db);
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 1dbc4f371..2dd779b66 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -145,11 +145,6 @@ impl CrateDefMap {
145 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 145 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
146 } 146 }
147 } 147 }
148 PathKind::Type(_) => {
149 // This is handled in `infer::infer_path_expr`
150 // The result returned here does not matter
151 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
152 }
153 }; 148 };
154 149
155 for (i, segment) in segments { 150 for (i, segment) in segments {
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index 5b03fe365..5e24cb94d 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -112,3 +112,24 @@ fn glob_enum() {
112 "### 112 "###
113 ); 113 );
114} 114}
115
116#[test]
117fn glob_enum_group() {
118 covers!(glob_enum_group);
119 let map = def_map(
120 "
121 //- /lib.rs
122 enum Foo {
123 Bar, Baz
124 }
125 use self::Foo::{*};
126 ",
127 );
128 assert_snapshot!(map, @r###"
129 â‹®crate
130 â‹®Bar: t v
131 â‹®Baz: t v
132 â‹®Foo: t
133 "###
134 );
135}
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 9e37ac416..00325cd99 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -18,6 +18,18 @@ pub struct ModPath {
18 pub segments: Vec<Name>, 18 pub segments: Vec<Name>,
19} 19}
20 20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub enum PathKind {
23 Plain,
24 /// `self::` is `Super(0)`
25 Super(u8),
26 Crate,
27 /// Absolute path (::foo)
28 Abs,
29 /// `$crate` from macro expansion
30 DollarCrate(CrateId),
31}
32
21impl ModPath { 33impl ModPath {
22 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { 34 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
23 lower::lower_path(path, hygiene).map(|it| it.mod_path) 35 lower::lower_path(path, hygiene).map(|it| it.mod_path)
@@ -70,6 +82,9 @@ impl ModPath {
70 82
71#[derive(Debug, Clone, PartialEq, Eq, Hash)] 83#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub struct Path { 84pub struct Path {
85 /// Type based path like `<T>::foo`.
86 /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
87 type_anchor: Option<Box<TypeRef>>,
73 mod_path: ModPath, 88 mod_path: ModPath,
74 /// Invariant: the same len as self.path.segments 89 /// Invariant: the same len as self.path.segments
75 generic_args: Vec<Option<Arc<GenericArgs>>>, 90 generic_args: Vec<Option<Arc<GenericArgs>>>,
@@ -97,19 +112,6 @@ pub enum GenericArg {
97 // or lifetime... 112 // or lifetime...
98} 113}
99 114
100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
101pub enum PathKind {
102 Plain,
103 Super(u8),
104 Crate,
105 // Absolute path
106 Abs,
107 // Type based path like `<T>::foo`
108 Type(Box<TypeRef>),
109 // `$crate` from macro expansion
110 DollarCrate(CrateId),
111}
112
113impl Path { 115impl Path {
114 /// Converts an `ast::Path` to `Path`. Works with use trees. 116 /// Converts an `ast::Path` to `Path`. Works with use trees.
115 /// DEPRECATED: It does not handle `$crate` from macro call. 117 /// DEPRECATED: It does not handle `$crate` from macro call.
@@ -125,18 +127,17 @@ impl Path {
125 127
126 /// Converts an `ast::NameRef` into a single-identifier `Path`. 128 /// Converts an `ast::NameRef` into a single-identifier `Path`.
127 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { 129 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
128 Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] } 130 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
129 }
130
131 /// `true` if this path is just a standalone `self`
132 pub fn is_self(&self) -> bool {
133 self.mod_path.is_self()
134 } 131 }
135 132
136 pub fn kind(&self) -> &PathKind { 133 pub fn kind(&self) -> &PathKind {
137 &self.mod_path.kind 134 &self.mod_path.kind
138 } 135 }
139 136
137 pub fn type_anchor(&self) -> Option<&TypeRef> {
138 self.type_anchor.as_ref().map(|it| &**it)
139 }
140
140 pub fn segments(&self) -> PathSegments<'_> { 141 pub fn segments(&self) -> PathSegments<'_> {
141 PathSegments { 142 PathSegments {
142 segments: self.mod_path.segments.as_slice(), 143 segments: self.mod_path.segments.as_slice(),
@@ -153,6 +154,7 @@ impl Path {
153 return None; 154 return None;
154 } 155 }
155 let res = Path { 156 let res = Path {
157 type_anchor: self.type_anchor.clone(),
156 mod_path: ModPath { 158 mod_path: ModPath {
157 kind: self.mod_path.kind.clone(), 159 kind: self.mod_path.kind.clone(),
158 segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), 160 segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
@@ -225,6 +227,7 @@ impl GenericArgs {
225impl From<Name> for Path { 227impl From<Name> for Path {
226 fn from(name: Name) -> Path { 228 fn from(name: Name) -> Path {
227 Path { 229 Path {
230 type_anchor: None,
228 mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)), 231 mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)),
229 generic_args: vec![None], 232 generic_args: vec![None],
230 } 233 }
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index c71b52d89..62aafd508 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -22,6 +22,7 @@ pub(super) use lower_use::lower_use_tree;
22/// It correctly handles `$crate` based path from macro call. 22/// It correctly handles `$crate` based path from macro call.
23pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 23pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
24 let mut kind = PathKind::Plain; 24 let mut kind = PathKind::Plain;
25 let mut type_anchor = None;
25 let mut segments = Vec::new(); 26 let mut segments = Vec::new();
26 let mut generic_args = Vec::new(); 27 let mut generic_args = Vec::new();
27 loop { 28 loop {
@@ -63,7 +64,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
63 match trait_ref { 64 match trait_ref {
64 // <T>::foo 65 // <T>::foo
65 None => { 66 None => {
66 kind = PathKind::Type(Box::new(self_type)); 67 type_anchor = Some(Box::new(self_type));
68 kind = PathKind::Plain;
67 } 69 }
68 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo 70 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
69 Some(trait_ref) => { 71 Some(trait_ref) => {
@@ -111,7 +113,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
111 segments.reverse(); 113 segments.reverse();
112 generic_args.reverse(); 114 generic_args.reverse();
113 let mod_path = ModPath { kind, segments }; 115 let mod_path = ModPath { kind, segments };
114 return Some(Path { mod_path, generic_args }); 116 return Some(Path { type_anchor, mod_path, generic_args });
115 117
116 fn qualifier(path: &ast::Path) -> Option<ast::Path> { 118 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
117 if let Some(q) = path.qualifier() { 119 if let Some(q) = path.qualifier() {
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index 062c02063..3218eaf0a 100644
--- a/crates/ra_hir_def/src/path/lower/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -9,6 +9,7 @@ use hir_expand::{
9 name::{AsName, Name}, 9 name::{AsName, Name},
10}; 10};
11use ra_syntax::ast::{self, NameOwner}; 11use ra_syntax::ast::{self, NameOwner};
12use test_utils::tested_by;
12 13
13use crate::path::{ModPath, PathKind}; 14use crate::path::{ModPath, PathKind};
14 15
@@ -34,6 +35,7 @@ pub(crate) fn lower_use_tree(
34 } 35 }
35 } else { 36 } else {
36 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); 37 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
38 let is_glob = tree.has_star();
37 if let Some(ast_path) = tree.path() { 39 if let Some(ast_path) = tree.path() {
38 // Handle self in a path. 40 // Handle self in a path.
39 // E.g. `use something::{self, <...>}` 41 // E.g. `use something::{self, <...>}`
@@ -48,11 +50,15 @@ pub(crate) fn lower_use_tree(
48 } 50 }
49 } 51 }
50 if let Some(path) = convert_path(prefix, ast_path, hygiene) { 52 if let Some(path) = convert_path(prefix, ast_path, hygiene) {
51 let is_glob = tree.has_star();
52 cb(path, &tree, is_glob, alias) 53 cb(path, &tree, is_glob, alias)
53 } 54 }
54 // FIXME: report errors somewhere 55 // FIXME: report errors somewhere
55 // We get here if we do 56 // We get here if we do
57 } else if is_glob {
58 tested_by!(glob_enum_group);
59 if let Some(prefix) = prefix {
60 cb(prefix, &tree, is_glob, None)
61 }
56 } 62 }
57 } 63 }
58} 64}
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 2694c0438..af9d194f8 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -17,9 +17,9 @@ use crate::{
17 nameres::{BuiltinShadowMode, CrateDefMap}, 17 nameres::{BuiltinShadowMode, CrateDefMap},
18 path::{ModPath, PathKind}, 18 path::{ModPath, PathKind},
19 per_ns::PerNs, 19 per_ns::PerNs,
20 AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, 20 AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
21 HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, 21 FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
22 TypeAliasId, TypeParamId, VariantId, 22 StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId,
23}; 23};
24 24
25#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
@@ -583,9 +583,18 @@ impl HasResolver for DefWithBodyId {
583impl HasResolver for ContainerId { 583impl HasResolver for ContainerId {
584 fn resolver(self, db: &impl DefDatabase) -> Resolver { 584 fn resolver(self, db: &impl DefDatabase) -> Resolver {
585 match self { 585 match self {
586 ContainerId::TraitId(it) => it.resolver(db),
587 ContainerId::ImplId(it) => it.resolver(db),
588 ContainerId::ModuleId(it) => it.resolver(db), 586 ContainerId::ModuleId(it) => it.resolver(db),
587 ContainerId::DefWithBodyId(it) => it.resolver(db),
588 }
589 }
590}
591
592impl HasResolver for AssocContainerId {
593 fn resolver(self, db: &impl DefDatabase) -> Resolver {
594 match self {
595 AssocContainerId::ContainerId(it) => it.resolver(db),
596 AssocContainerId::TraitId(it) => it.resolver(db),
597 AssocContainerId::ImplId(it) => it.resolver(db),
589 } 598 }
590 } 599 }
591} 600}
diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs
index 20200d1db..499375b80 100644
--- a/crates/ra_hir_def/src/src.rs
+++ b/crates/ra_hir_def/src/src.rs
@@ -2,94 +2,28 @@
2 2
3use hir_expand::InFile; 3use hir_expand::InFile;
4use ra_arena::map::ArenaMap; 4use ra_arena::map::ArenaMap;
5use ra_syntax::ast; 5use ra_syntax::AstNode;
6 6
7use crate::{ 7use crate::{db::DefDatabase, AssocItemLoc, ItemLoc};
8 db::DefDatabase, ConstLoc, EnumLoc, FunctionLoc, ImplLoc, StaticLoc, StructLoc, TraitLoc,
9 TypeAliasLoc, UnionLoc,
10};
11 8
12pub trait HasSource { 9pub trait HasSource {
13 type Value; 10 type Value;
14 fn source(&self, db: &impl DefDatabase) -> InFile<Self::Value>; 11 fn source(&self, db: &impl DefDatabase) -> InFile<Self::Value>;
15} 12}
16 13
17impl HasSource for FunctionLoc { 14impl<N: AstNode> HasSource for AssocItemLoc<N> {
18 type Value = ast::FnDef; 15 type Value = N;
19 16
20 fn source(&self, db: &impl DefDatabase) -> InFile<ast::FnDef> { 17 fn source(&self, db: &impl DefDatabase) -> InFile<N> {
21 let node = self.ast_id.to_node(db); 18 let node = self.ast_id.to_node(db);
22 InFile::new(self.ast_id.file_id, node) 19 InFile::new(self.ast_id.file_id, node)
23 } 20 }
24} 21}
25 22
26impl HasSource for TypeAliasLoc { 23impl<N: AstNode> HasSource for ItemLoc<N> {
27 type Value = ast::TypeAliasDef; 24 type Value = N;
28 25
29 fn source(&self, db: &impl DefDatabase) -> InFile<ast::TypeAliasDef> { 26 fn source(&self, db: &impl DefDatabase) -> InFile<N> {
30 let node = self.ast_id.to_node(db);
31 InFile::new(self.ast_id.file_id, node)
32 }
33}
34
35impl HasSource for ConstLoc {
36 type Value = ast::ConstDef;
37
38 fn source(&self, db: &impl DefDatabase) -> InFile<ast::ConstDef> {
39 let node = self.ast_id.to_node(db);
40 InFile::new(self.ast_id.file_id, node)
41 }
42}
43
44impl HasSource for StaticLoc {
45 type Value = ast::StaticDef;
46
47 fn source(&self, db: &impl DefDatabase) -> InFile<ast::StaticDef> {
48 let node = self.ast_id.to_node(db);
49 InFile::new(self.ast_id.file_id, node)
50 }
51}
52
53impl HasSource for ImplLoc {
54 type Value = ast::ImplBlock;
55
56 fn source(&self, db: &impl DefDatabase) -> InFile<ast::ImplBlock> {
57 let node = self.ast_id.to_node(db);
58 InFile::new(self.ast_id.file_id, node)
59 }
60}
61
62impl HasSource for TraitLoc {
63 type Value = ast::TraitDef;
64
65 fn source(&self, db: &impl DefDatabase) -> InFile<ast::TraitDef> {
66 let node = self.ast_id.to_node(db);
67 InFile::new(self.ast_id.file_id, node)
68 }
69}
70
71impl HasSource for StructLoc {
72 type Value = ast::StructDef;
73
74 fn source(&self, db: &impl DefDatabase) -> InFile<ast::StructDef> {
75 let node = self.ast_id.to_node(db);
76 InFile::new(self.ast_id.file_id, node)
77 }
78}
79
80impl HasSource for UnionLoc {
81 type Value = ast::UnionDef;
82
83 fn source(&self, db: &impl DefDatabase) -> InFile<ast::UnionDef> {
84 let node = self.ast_id.to_node(db);
85 InFile::new(self.ast_id.file_id, node)
86 }
87}
88
89impl HasSource for EnumLoc {
90 type Value = ast::EnumDef;
91
92 fn source(&self, db: &impl DefDatabase) -> InFile<ast::EnumDef> {
93 let node = self.ast_id.to_node(db); 27 let node = self.ast_id.to_node(db);
94 InFile::new(self.ast_id.file_id, node) 28 InFile::new(self.ast_id.file_id, node)
95 } 29 }
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 9bb3ece6c..dcca1bace 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -10,6 +10,7 @@ pub struct HirFormatter<'a, 'b, DB> {
10 buf: String, 10 buf: String,
11 curr_size: usize, 11 curr_size: usize,
12 max_size: Option<usize>, 12 max_size: Option<usize>,
13 should_display_default_types: bool,
13} 14}
14 15
15pub trait HirDisplay { 16pub trait HirDisplay {
@@ -19,7 +20,7 @@ pub trait HirDisplay {
19 where 20 where
20 Self: Sized, 21 Self: Sized,
21 { 22 {
22 HirDisplayWrapper(db, self, None) 23 HirDisplayWrapper(db, self, None, true)
23 } 24 }
24 25
25 fn display_truncated<'a, DB>( 26 fn display_truncated<'a, DB>(
@@ -30,7 +31,7 @@ pub trait HirDisplay {
30 where 31 where
31 Self: Sized, 32 Self: Sized,
32 { 33 {
33 HirDisplayWrapper(db, self, max_size) 34 HirDisplayWrapper(db, self, max_size, false)
34 } 35 }
35} 36}
36 37
@@ -72,9 +73,13 @@ where
72 false 73 false
73 } 74 }
74 } 75 }
76
77 pub fn should_display_default_types(&self) -> bool {
78 self.should_display_default_types
79 }
75} 80}
76 81
77pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<usize>); 82pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<usize>, bool);
78 83
79impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> 84impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T>
80where 85where
@@ -88,6 +93,7 @@ where
88 buf: String::with_capacity(20), 93 buf: String::with_capacity(20),
89 curr_size: 0, 94 curr_size: 0,
90 max_size: self.2, 95 max_size: self.2,
96 should_display_default_types: self.3,
91 }) 97 })
92 } 98 }
93} 99}
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 011c6c5c6..8be567917 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 AdtId, ContainerId, Lookup, StructFieldId, 11 AdtId, AssocContainerId, Lookup, StructFieldId,
12}; 12};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
@@ -676,7 +676,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
676 // add obligation for trait implementation, if this is a trait method 676 // add obligation for trait implementation, if this is a trait method
677 match def { 677 match def {
678 CallableDef::FunctionId(f) => { 678 CallableDef::FunctionId(f) => {
679 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { 679 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db).container {
680 // construct a TraitDef 680 // construct a TraitDef
681 let substs = 681 let substs =
682 a_ty.parameters.prefix(generics(self.db, trait_.into()).len()); 682 a_ty.parameters.prefix(generics(self.db, trait_.into()).len());
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 3bae0ca6c..ffd358367 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -3,9 +3,9 @@
3use std::iter; 3use std::iter;
4 4
5use hir_def::{ 5use hir_def::{
6 path::{Path, PathKind, PathSegment}, 6 path::{Path, PathSegment},
7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
8 AssocItemId, ContainerId, Lookup, 8 AssocContainerId, AssocItemId, Lookup,
9}; 9};
10use hir_expand::name::Name; 10use hir_expand::name::Name;
11 11
@@ -32,7 +32,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
32 path: &Path, 32 path: &Path,
33 id: ExprOrPatId, 33 id: ExprOrPatId,
34 ) -> Option<Ty> { 34 ) -> Option<Ty> {
35 let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() { 35 let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
36 if path.segments().is_empty() { 36 if path.segments().is_empty() {
37 // This can't actually happen syntax-wise 37 // This can't actually happen syntax-wise
38 return None; 38 return None;
@@ -209,7 +209,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
209 AssocItemId::TypeAliasId(_) => unreachable!(), 209 AssocItemId::TypeAliasId(_) => unreachable!(),
210 }; 210 };
211 let substs = match container { 211 let substs = match container {
212 ContainerId::ImplId(impl_id) => { 212 AssocContainerId::ImplId(impl_id) => {
213 let impl_substs = Substs::build_for_def(self.db, impl_id) 213 let impl_substs = Substs::build_for_def(self.db, impl_id)
214 .fill(iter::repeat_with(|| self.table.new_type_var())) 214 .fill(iter::repeat_with(|| self.table.new_type_var()))
215 .build(); 215 .build();
@@ -221,7 +221,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
221 self.unify(&impl_self_ty, &ty); 221 self.unify(&impl_self_ty, &ty);
222 Some(substs) 222 Some(substs)
223 } 223 }
224 ContainerId::TraitId(trait_) => { 224 AssocContainerId::TraitId(trait_) => {
225 // we're picking this method 225 // we're picking this method
226 let trait_substs = Substs::build_for_def(self.db, trait_) 226 let trait_substs = Substs::build_for_def(self.db, trait_)
227 .push(ty.clone()) 227 .push(ty.clone())
@@ -237,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
237 })); 237 }));
238 Some(substs) 238 Some(substs)
239 } 239 }
240 ContainerId::ModuleId(_) => None, 240 AssocContainerId::ContainerId(_) => None,
241 }; 241 };
242 242
243 self.write_assoc_resolution(id, item.into()); 243 self.write_assoc_resolution(id, item.into());
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 3ad913e55..7310ef10d 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -44,8 +44,8 @@ use std::sync::Arc;
44use std::{fmt, iter, mem}; 44use std::{fmt, iter, mem};
45 45
46use hir_def::{ 46use hir_def::{
47 expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule, 47 expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
48 Lookup, TraitId, TypeAliasId, 48 HasModule, Lookup, TraitId, TypeAliasId,
49}; 49};
50use hir_expand::name::Name; 50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId}; 51use ra_db::{impl_intern_key, salsa, CrateId};
@@ -251,7 +251,7 @@ impl ProjectionTy {
251 251
252 fn trait_(&self, db: &impl HirDatabase) -> TraitId { 252 fn trait_(&self, db: &impl HirDatabase) -> TraitId {
253 match self.associated_ty.lookup(db).container { 253 match self.associated_ty.lookup(db).container {
254 ContainerId::TraitId(it) => it, 254 AssocContainerId::TraitId(it) => it,
255 _ => panic!("projection ty without parent trait"), 255 _ => panic!("projection ty without parent trait"),
256 } 256 }
257 } 257 }
@@ -906,13 +906,44 @@ impl HirDisplay for ApplicationTy {
906 write!(f, "{}", name)?; 906 write!(f, "{}", name)?;
907 if self.parameters.len() > 0 { 907 if self.parameters.len() > 0 {
908 write!(f, "<")?; 908 write!(f, "<")?;
909 f.write_joined(&*self.parameters.0, ", ")?; 909
910 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
911 let parameters_to_write = if f.should_display_default_types() {
912 self.parameters.0.as_ref()
913 } else {
914 match self
915 .ctor
916 .as_generic_def()
917 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
918 .filter(|defaults| !defaults.is_empty())
919 {
920 Option::None => self.parameters.0.as_ref(),
921 Option::Some(default_parameters) => {
922 for (i, parameter) in self.parameters.into_iter().enumerate() {
923 match (parameter, default_parameters.get(i)) {
924 (&Ty::Unknown, _) | (_, None) => {
925 non_default_parameters.push(parameter.clone())
926 }
927 (_, Some(default_parameter))
928 if parameter != default_parameter =>
929 {
930 non_default_parameters.push(parameter.clone())
931 }
932 _ => (),
933 }
934 }
935 &non_default_parameters
936 }
937 }
938 };
939
940 f.write_joined(parameters_to_write, ", ")?;
910 write!(f, ">")?; 941 write!(f, ">")?;
911 } 942 }
912 } 943 }
913 TypeCtor::AssociatedType(type_alias) => { 944 TypeCtor::AssociatedType(type_alias) => {
914 let trait_ = match type_alias.lookup(f.db).container { 945 let trait_ = match type_alias.lookup(f.db).container {
915 ContainerId::TraitId(it) => it, 946 AssocContainerId::TraitId(it) => it,
916 _ => panic!("not an associated type"), 947 _ => panic!("not an associated type"),
917 }; 948 };
918 let trait_name = f.db.trait_data(trait_).name.clone(); 949 let trait_name = f.db.trait_data(trait_).name.clone();
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index a4ddfc8ef..af3db2e1d 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -11,7 +11,7 @@ use std::sync::Arc;
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 generics::WherePredicate, 13 generics::WherePredicate,
14 path::{GenericArg, Path, PathKind, PathSegment, PathSegments}, 14 path::{GenericArg, Path, PathSegment, PathSegments},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, 17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
@@ -101,7 +101,7 @@ impl Ty {
101 TypeRef::Path(path) => path, 101 TypeRef::Path(path) => path,
102 _ => return None, 102 _ => return None,
103 }; 103 };
104 if let PathKind::Type(_) = path.kind() { 104 if path.type_anchor().is_some() {
105 return None; 105 return None;
106 } 106 }
107 if path.segments().len() > 1 { 107 if path.segments().len() > 1 {
@@ -202,7 +202,7 @@ impl Ty {
202 202
203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
204 // Resolve the path (in type namespace) 204 // Resolve the path (in type namespace)
205 if let PathKind::Type(type_ref) = path.kind() { 205 if let Some(type_ref) = path.type_anchor() {
206 let ty = Ty::from_hir(db, resolver, &type_ref); 206 let ty = Ty::from_hir(db, resolver, &type_ref);
207 return Ty::from_type_relative_path(db, resolver, ty, path.segments()); 207 return Ty::from_type_relative_path(db, resolver, ty, path.segments());
208 } 208 }
@@ -697,8 +697,8 @@ impl CallableDef {
697 pub fn krate(self, db: &impl HirDatabase) -> CrateId { 697 pub fn krate(self, db: &impl HirDatabase) -> CrateId {
698 match self { 698 match self {
699 CallableDef::FunctionId(f) => f.lookup(db).module(db), 699 CallableDef::FunctionId(f) => f.lookup(db).module(db),
700 CallableDef::StructId(s) => s.lookup(db).container, 700 CallableDef::StructId(s) => s.lookup(db).container.module(db),
701 CallableDef::EnumVariantId(e) => e.parent.lookup(db).container, 701 CallableDef::EnumVariantId(e) => e.parent.lookup(db).container.module(db),
702 } 702 }
703 .krate 703 .krate
704 } 704 }
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 848e306e9..92fb4c081 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -6,8 +6,8 @@ use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, FunctionId, 9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId,
10 HasModule, ImplId, Lookup, TraitId, 10 AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
@@ -134,7 +134,7 @@ impl Ty {
134 LangItemTarget::ImplBlockId(it) => Some(it), 134 LangItemTarget::ImplBlockId(it) => Some(it),
135 _ => None, 135 _ => None,
136 }) 136 })
137 .map(|it| it.lookup(db).container.krate) 137 .map(|it| it.lookup(db).container.module(db).krate)
138 .collect(); 138 .collect();
139 Some(res) 139 Some(res)
140 } 140 }
@@ -451,12 +451,12 @@ fn transform_receiver_ty(
451 self_ty: &Canonical<Ty>, 451 self_ty: &Canonical<Ty>,
452) -> Option<Ty> { 452) -> Option<Ty> {
453 let substs = match function_id.lookup(db).container { 453 let substs = match function_id.lookup(db).container {
454 hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, function_id) 454 AssocContainerId::TraitId(_) => Substs::build_for_def(db, function_id)
455 .push(self_ty.value.clone()) 455 .push(self_ty.value.clone())
456 .fill_with_unknown() 456 .fill_with_unknown()
457 .build(), 457 .build(),
458 hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, 458 AssocContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?,
459 hir_def::ContainerId::ModuleId(_) => unreachable!(), 459 AssocContainerId::ContainerId(_) => unreachable!(),
460 }; 460 };
461 let sig = db.callable_item_signature(function_id.into()); 461 let sig = db.callable_item_signature(function_id.into());
462 Some(sig.params()[0].clone().subst(&substs)) 462 Some(sig.params()[0].clone().subst(&substs))
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index fc21872b2..5eb032d86 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -9,7 +9,9 @@ use chalk_ir::{
9}; 9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_def::{AssocItemId, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; 12use hir_def::{
13 AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId,
14};
13use ra_db::{ 15use ra_db::{
14 salsa::{InternId, InternKey}, 16 salsa::{InternId, InternKey},
15 CrateId, 17 CrateId,
@@ -542,7 +544,7 @@ pub(crate) fn associated_ty_data_query(
542 debug!("associated_ty_data {:?}", id); 544 debug!("associated_ty_data {:?}", id);
543 let type_alias: TypeAliasId = from_chalk(db, id); 545 let type_alias: TypeAliasId = from_chalk(db, id);
544 let trait_ = match type_alias.lookup(db).container { 546 let trait_ = match type_alias.lookup(db).container {
545 ContainerId::TraitId(t) => t, 547 AssocContainerId::TraitId(t) => t,
546 _ => panic!("associated type not in trait"), 548 _ => panic!("associated type not in trait"),
547 }; 549 };
548 let generic_params = generics(db, type_alias.into()); 550 let generic_params = generics(db, type_alias.into());
@@ -591,7 +593,7 @@ pub(crate) fn trait_datum_query(
591 let bound_vars = Substs::bound_vars(&generic_params); 593 let bound_vars = Substs::bound_vars(&generic_params);
592 let flags = chalk_rust_ir::TraitFlags { 594 let flags = chalk_rust_ir::TraitFlags {
593 auto: trait_data.auto, 595 auto: trait_data.auto,
594 upstream: trait_.lookup(db).container.krate != krate, 596 upstream: trait_.lookup(db).container.module(db).krate != krate,
595 non_enumerable: true, 597 non_enumerable: true,
596 coinductive: false, // only relevant for Chalk testing 598 coinductive: false, // only relevant for Chalk testing
597 // FIXME set these flags correctly 599 // FIXME set these flags correctly
@@ -671,7 +673,7 @@ fn impl_block_datum(
671 let bound_vars = Substs::bound_vars(&generic_params); 673 let bound_vars = Substs::bound_vars(&generic_params);
672 let trait_ref = trait_ref.subst(&bound_vars); 674 let trait_ref = trait_ref.subst(&bound_vars);
673 let trait_ = trait_ref.trait_; 675 let trait_ = trait_ref.trait_;
674 let impl_type = if impl_id.lookup(db).container.krate == krate { 676 let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
675 chalk_rust_ir::ImplType::Local 677 chalk_rust_ir::ImplType::Local
676 } else { 678 } else {
677 chalk_rust_ir::ImplType::External 679 chalk_rust_ir::ImplType::External
@@ -755,7 +757,7 @@ fn type_alias_associated_ty_value(
755) -> Arc<AssociatedTyValue<ChalkIr>> { 757) -> Arc<AssociatedTyValue<ChalkIr>> {
756 let type_alias_data = db.type_alias_data(type_alias); 758 let type_alias_data = db.type_alias_data(type_alias);
757 let impl_id = match type_alias.lookup(db).container { 759 let impl_id = match type_alias.lookup(db).container {
758 ContainerId::ImplId(it) => it, 760 AssocContainerId::ImplId(it) => it,
759 _ => panic!("assoc ty value should be in impl"), 761 _ => panic!("assoc ty value should be in impl"),
760 }; 762 };
761 763
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index 29799a8cb..0b1806a84 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -9,7 +9,7 @@ use hir_def::{
9 path::Path, 9 path::Path,
10 resolver::{HasResolver, TypeNs}, 10 resolver::{HasResolver, TypeNs},
11 type_ref::TypeRef, 11 type_ref::TypeRef,
12 ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, 12 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId,
13}; 13};
14use hir_expand::name::{name, Name}; 14use hir_expand::name::{name, Name};
15 15
@@ -155,8 +155,8 @@ fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<Generi
155 }; 155 };
156 156
157 match container { 157 match container {
158 ContainerId::ImplId(it) => Some(it.into()), 158 AssocContainerId::ImplId(it) => Some(it.into()),
159 ContainerId::TraitId(it) => Some(it.into()), 159 AssocContainerId::TraitId(it) => Some(it.into()),
160 ContainerId::ModuleId(_) => None, 160 AssocContainerId::ContainerId(_) => None,
161 } 161 }
162} 162}
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index b3c323d38..2c2b6fa48 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -1,24 +1,26 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_db::SourceDatabase; 3use hir::db::AstDatabase;
4use ra_syntax::{ 4use ra_syntax::{
5 algo::ancestors_at_offset,
6 ast::{self, ArgListOwner}, 5 ast::{self, ArgListOwner},
7 match_ast, AstNode, SyntaxNode, TextUnit, 6 match_ast, AstNode, SyntaxNode,
8}; 7};
9use test_utils::tested_by; 8use test_utils::tested_by;
10 9
11use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature}; 10use crate::{
11 db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature,
12};
12 13
13/// Computes parameter information for the given call expression. 14/// Computes parameter information for the given call expression.
14pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { 15pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
15 let parse = db.parse(position.file_id); 16 let file = db.parse_or_expand(position.file_id.into())?;
16 let syntax = parse.tree().syntax().clone(); 17 let token = file.token_at_offset(position.offset).next()?;
18 let token = descend_into_macros(db, position.file_id, token);
17 19
18 // Find the calling expression and it's NameRef 20 // Find the calling expression and it's NameRef
19 let calling_node = FnCallNode::with_node(&syntax, position.offset)?; 21 let calling_node = FnCallNode::with_node(&token.value.parent())?;
20 let name_ref = calling_node.name_ref()?; 22 let name_ref = calling_node.name_ref()?;
21 let name_ref = hir::InFile::new(position.file_id.into(), name_ref.syntax()); 23 let name_ref = token.with_value(name_ref.syntax());
22 24
23 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); 25 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None);
24 let (mut call_info, has_self) = match &calling_node { 26 let (mut call_info, has_self) = match &calling_node {
@@ -93,8 +95,8 @@ enum FnCallNode {
93} 95}
94 96
95impl FnCallNode { 97impl FnCallNode {
96 fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option<FnCallNode> { 98 fn with_node(syntax: &SyntaxNode) -> Option<FnCallNode> {
97 ancestors_at_offset(syntax, offset).find_map(|node| { 99 syntax.ancestors().find_map(|node| {
98 match_ast! { 100 match_ast! {
99 match node { 101 match node {
100 ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, 102 ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) },
@@ -589,4 +591,25 @@ fn f() {
589 assert_eq!(info.label(), "foo!()"); 591 assert_eq!(info.label(), "foo!()");
590 assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string())); 592 assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string()));
591 } 593 }
594
595 #[test]
596 fn fn_signature_for_call_in_macro() {
597 let info = call_info(
598 r#"
599 macro_rules! id {
600 ($($tt:tt)*) => { $($tt)* }
601 }
602 fn foo() {
603
604 }
605 id! {
606 fn bar() {
607 foo(<|>);
608 }
609 }
610 "#,
611 );
612
613 assert_eq!(info.label(), "fn foo()");
614 }
592} 615}
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index 6a6b49afd..b9ae67828 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -328,22 +328,23 @@ impl ToNav for hir::AssocItem {
328impl ToNav for hir::Local { 328impl ToNav for hir::Local {
329 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 329 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
330 let src = self.source(db); 330 let src = self.source(db);
331 let (full_range, focus_range) = match src.value { 331 let node = match &src.value {
332 Either::Left(it) => { 332 Either::Left(bind_pat) => {
333 (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) 333 bind_pat.name().map_or_else(|| bind_pat.syntax().clone(), |it| it.syntax().clone())
334 } 334 }
335 Either::Right(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), 335 Either::Right(it) => it.syntax().clone(),
336 }; 336 };
337 let full_range = original_range(db, src.with_value(&node));
337 let name = match self.name(db) { 338 let name = match self.name(db) {
338 Some(it) => it.to_string().into(), 339 Some(it) => it.to_string().into(),
339 None => "".into(), 340 None => "".into(),
340 }; 341 };
341 NavigationTarget { 342 NavigationTarget {
342 file_id: src.file_id.original_file(db), 343 file_id: full_range.file_id,
343 name, 344 name,
344 kind: BIND_PAT, 345 kind: BIND_PAT,
345 full_range, 346 full_range: full_range.range,
346 focus_range, 347 focus_range: None,
347 container_name: None, 348 container_name: None,
348 description: None, 349 description: None,
349 docs: None, 350 docs: None,
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index bee8e9df2..9b5744789 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -225,35 +225,40 @@ mod tests {
225 225
226 use crate::mock_analysis::analysis_and_position; 226 use crate::mock_analysis::analysis_and_position;
227 227
228 fn check_goto(fixture: &str, expected: &str) { 228 fn check_goto(fixture: &str, expected: &str, expected_range: &str) {
229 let (analysis, pos) = analysis_and_position(fixture); 229 let (analysis, pos) = analysis_and_position(fixture);
230 230
231 let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; 231 let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info;
232 assert_eq!(navs.len(), 1); 232 assert_eq!(navs.len(), 1);
233 let nav = navs.pop().unwrap();
234 nav.assert_match(expected);
235 }
236
237 fn check_goto_with_range_content(fixture: &str, expected: &str, expected_range: &str) {
238 let (analysis, pos) = analysis_and_position(fixture);
239 233
240 let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info;
241 assert_eq!(navs.len(), 1);
242 let nav = navs.pop().unwrap(); 234 let nav = navs.pop().unwrap();
243 let file_text = analysis.file_text(pos.file_id).unwrap(); 235 let file_text = analysis.file_text(nav.file_id()).unwrap();
236
237 let mut actual = file_text[nav.full_range()].to_string();
238 if let Some(focus) = nav.focus_range() {
239 actual += "|";
240 actual += &file_text[focus];
241 }
244 242
245 let actual_full_range = &file_text[nav.full_range()]; 243 if !expected_range.contains("...") {
246 let actual_range = &file_text[nav.range()]; 244 test_utils::assert_eq_text!(&actual, expected_range);
245 } else {
246 let mut parts = expected_range.split("...");
247 let prefix = parts.next().unwrap();
248 let suffix = parts.next().unwrap();
249 assert!(
250 actual.starts_with(prefix) && actual.ends_with(suffix),
251 "\nExpected: {}\n Actual: {}\n",
252 expected_range,
253 actual
254 );
255 }
247 256
248 test_utils::assert_eq_text!(
249 &format!("{}|{}", actual_full_range, actual_range),
250 expected_range
251 );
252 nav.assert_match(expected); 257 nav.assert_match(expected);
253 } 258 }
254 259
255 #[test] 260 #[test]
256 fn goto_definition_works_in_items() { 261 fn goto_def_in_items() {
257 check_goto( 262 check_goto(
258 " 263 "
259 //- /lib.rs 264 //- /lib.rs
@@ -261,11 +266,12 @@ mod tests {
261 enum E { X(Foo<|>) } 266 enum E { X(Foo<|>) }
262 ", 267 ",
263 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", 268 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
269 "struct Foo;|Foo",
264 ); 270 );
265 } 271 }
266 272
267 #[test] 273 #[test]
268 fn goto_definition_works_at_start_of_item() { 274 fn goto_def_at_start_of_item() {
269 check_goto( 275 check_goto(
270 " 276 "
271 //- /lib.rs 277 //- /lib.rs
@@ -273,6 +279,7 @@ mod tests {
273 enum E { X(<|>Foo) } 279 enum E { X(<|>Foo) }
274 ", 280 ",
275 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", 281 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
282 "struct Foo;|Foo",
276 ); 283 );
277 } 284 }
278 285
@@ -285,61 +292,65 @@ mod tests {
285 mod a; 292 mod a;
286 mod b; 293 mod b;
287 enum E { X(Foo<|>) } 294 enum E { X(Foo<|>) }
295
288 //- /a.rs 296 //- /a.rs
289 struct Foo; 297 struct Foo;
298
290 //- /b.rs 299 //- /b.rs
291 struct Foo; 300 struct Foo;
292 ", 301 ",
293 "Foo STRUCT_DEF FileId(2) [0; 11) [7; 10)", 302 "Foo STRUCT_DEF FileId(2) [0; 11) [7; 10)",
303 "struct Foo;|Foo",
294 ); 304 );
295 } 305 }
296 306
297 #[test] 307 #[test]
298 fn goto_definition_works_for_module_declaration() { 308 fn goto_def_for_module_declaration() {
299 check_goto( 309 check_goto(
300 " 310 "
301 //- /lib.rs 311 //- /lib.rs
302 mod <|>foo; 312 mod <|>foo;
313
303 //- /foo.rs 314 //- /foo.rs
304 // empty 315 // empty
305 ", 316 ",
306 "foo SOURCE_FILE FileId(2) [0; 10)", 317 "foo SOURCE_FILE FileId(2) [0; 10)",
318 "// empty\n\n",
307 ); 319 );
308 320
309 check_goto( 321 check_goto(
310 " 322 "
311 //- /lib.rs 323 //- /lib.rs
312 mod <|>foo; 324 mod <|>foo;
325
313 //- /foo/mod.rs 326 //- /foo/mod.rs
314 // empty 327 // empty
315 ", 328 ",
316 "foo SOURCE_FILE FileId(2) [0; 10)", 329 "foo SOURCE_FILE FileId(2) [0; 10)",
330 "// empty\n\n",
317 ); 331 );
318 } 332 }
319 333
320 #[test] 334 #[test]
321 fn goto_definition_works_for_macros() { 335 fn goto_def_for_macros() {
322 covers!(goto_definition_works_for_macros); 336 covers!(goto_def_for_macros);
323 check_goto( 337 check_goto(
324 " 338 "
325 //- /lib.rs 339 //- /lib.rs
326 macro_rules! foo { 340 macro_rules! foo { () => { () } }
327 () => {
328 {}
329 };
330 }
331 341
332 fn bar() { 342 fn bar() {
333 <|>foo!(); 343 <|>foo!();
334 } 344 }
335 ", 345 ",
336 "foo MACRO_CALL FileId(1) [0; 50) [13; 16)", 346 "foo MACRO_CALL FileId(1) [0; 33) [13; 16)",
347 "macro_rules! foo { () => { () } }|foo",
337 ); 348 );
338 } 349 }
339 350
340 #[test] 351 #[test]
341 fn goto_definition_works_for_macros_from_other_crates() { 352 fn goto_def_for_macros_from_other_crates() {
342 covers!(goto_definition_works_for_macros); 353 covers!(goto_def_for_macros);
343 check_goto( 354 check_goto(
344 " 355 "
345 //- /lib.rs 356 //- /lib.rs
@@ -350,18 +361,15 @@ mod tests {
350 361
351 //- /foo/lib.rs 362 //- /foo/lib.rs
352 #[macro_export] 363 #[macro_export]
353 macro_rules! foo { 364 macro_rules! foo { () => { () } }
354 () => {
355 {}
356 };
357 }
358 ", 365 ",
359 "foo MACRO_CALL FileId(2) [0; 66) [29; 32)", 366 "foo MACRO_CALL FileId(2) [0; 49) [29; 32)",
367 "#[macro_export]\nmacro_rules! foo { () => { () } }|foo",
360 ); 368 );
361 } 369 }
362 370
363 #[test] 371 #[test]
364 fn goto_definition_works_for_macros_in_use_tree() { 372 fn goto_def_for_macros_in_use_tree() {
365 check_goto( 373 check_goto(
366 " 374 "
367 //- /lib.rs 375 //- /lib.rs
@@ -369,19 +377,16 @@ mod tests {
369 377
370 //- /foo/lib.rs 378 //- /foo/lib.rs
371 #[macro_export] 379 #[macro_export]
372 macro_rules! foo { 380 macro_rules! foo { () => { () } }
373 () => {
374 {}
375 };
376 }
377 ", 381 ",
378 "foo MACRO_CALL FileId(2) [0; 66) [29; 32)", 382 "foo MACRO_CALL FileId(2) [0; 49) [29; 32)",
383 "#[macro_export]\nmacro_rules! foo { () => { () } }|foo",
379 ); 384 );
380 } 385 }
381 386
382 #[test] 387 #[test]
383 fn goto_definition_works_for_macro_defined_fn_with_arg() { 388 fn goto_def_for_macro_defined_fn_with_arg() {
384 check_goto_with_range_content( 389 check_goto(
385 " 390 "
386 //- /lib.rs 391 //- /lib.rs
387 macro_rules! define_fn { 392 macro_rules! define_fn {
@@ -400,8 +405,8 @@ mod tests {
400 } 405 }
401 406
402 #[test] 407 #[test]
403 fn goto_definition_works_for_macro_defined_fn_no_arg() { 408 fn goto_def_for_macro_defined_fn_no_arg() {
404 check_goto_with_range_content( 409 check_goto(
405 " 410 "
406 //- /lib.rs 411 //- /lib.rs
407 macro_rules! define_fn { 412 macro_rules! define_fn {
@@ -420,27 +425,28 @@ mod tests {
420 } 425 }
421 426
422 #[test] 427 #[test]
423 fn goto_definition_works_for_methods() { 428 fn goto_def_for_methods() {
424 covers!(goto_definition_works_for_methods); 429 covers!(goto_def_for_methods);
425 check_goto( 430 check_goto(
426 " 431 "
427 //- /lib.rs 432 //- /lib.rs
428 struct Foo; 433 struct Foo;
429 impl Foo { 434 impl Foo {
430 fn frobnicate(&self) { } 435 fn frobnicate(&self) { }
431 } 436 }
432 437
433 fn bar(foo: &Foo) { 438 fn bar(foo: &Foo) {
434 foo.frobnicate<|>(); 439 foo.frobnicate<|>();
435 } 440 }
436 ", 441 ",
437 "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", 442 "frobnicate FN_DEF FileId(1) [27; 51) [30; 40)",
443 "fn frobnicate(&self) { }|frobnicate",
438 ); 444 );
439 } 445 }
440 446
441 #[test] 447 #[test]
442 fn goto_definition_works_for_fields() { 448 fn goto_def_for_fields() {
443 covers!(goto_definition_works_for_fields); 449 covers!(goto_def_for_fields);
444 check_goto( 450 check_goto(
445 " 451 "
446 //- /lib.rs 452 //- /lib.rs
@@ -453,12 +459,13 @@ mod tests {
453 } 459 }
454 ", 460 ",
455 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", 461 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
462 "spam: u32|spam",
456 ); 463 );
457 } 464 }
458 465
459 #[test] 466 #[test]
460 fn goto_definition_works_for_record_fields() { 467 fn goto_def_for_record_fields() {
461 covers!(goto_definition_works_for_record_fields); 468 covers!(goto_def_for_record_fields);
462 check_goto( 469 check_goto(
463 " 470 "
464 //- /lib.rs 471 //- /lib.rs
@@ -473,6 +480,7 @@ mod tests {
473 } 480 }
474 ", 481 ",
475 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", 482 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
483 "spam: u32|spam",
476 ); 484 );
477 } 485 }
478 486
@@ -489,29 +497,31 @@ mod tests {
489 } 497 }
490 ", 498 ",
491 "TUPLE_FIELD_DEF FileId(1) [11; 14)", 499 "TUPLE_FIELD_DEF FileId(1) [11; 14)",
500 "u32",
492 ); 501 );
493 } 502 }
494 503
495 #[test] 504 #[test]
496 fn goto_definition_works_for_ufcs_inherent_methods() { 505 fn goto_def_for_ufcs_inherent_methods() {
497 check_goto( 506 check_goto(
498 " 507 "
499 //- /lib.rs 508 //- /lib.rs
500 struct Foo; 509 struct Foo;
501 impl Foo { 510 impl Foo {
502 fn frobnicate() { } 511 fn frobnicate() { }
503 } 512 }
504 513
505 fn bar(foo: &Foo) { 514 fn bar(foo: &Foo) {
506 Foo::frobnicate<|>(); 515 Foo::frobnicate<|>();
507 } 516 }
508 ", 517 ",
509 "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)", 518 "frobnicate FN_DEF FileId(1) [27; 46) [30; 40)",
519 "fn frobnicate() { }|frobnicate",
510 ); 520 );
511 } 521 }
512 522
513 #[test] 523 #[test]
514 fn goto_definition_works_for_ufcs_trait_methods_through_traits() { 524 fn goto_def_for_ufcs_trait_methods_through_traits() {
515 check_goto( 525 check_goto(
516 " 526 "
517 //- /lib.rs 527 //- /lib.rs
@@ -524,11 +534,12 @@ mod tests {
524 } 534 }
525 ", 535 ",
526 "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)", 536 "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)",
537 "fn frobnicate();|frobnicate",
527 ); 538 );
528 } 539 }
529 540
530 #[test] 541 #[test]
531 fn goto_definition_works_for_ufcs_trait_methods_through_self() { 542 fn goto_def_for_ufcs_trait_methods_through_self() {
532 check_goto( 543 check_goto(
533 " 544 "
534 //- /lib.rs 545 //- /lib.rs
@@ -543,6 +554,7 @@ mod tests {
543 } 554 }
544 ", 555 ",
545 "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)", 556 "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)",
557 "fn frobnicate();|frobnicate",
546 ); 558 );
547 } 559 }
548 560
@@ -559,6 +571,7 @@ mod tests {
559 } 571 }
560 ", 572 ",
561 "impl IMPL_BLOCK FileId(1) [12; 73)", 573 "impl IMPL_BLOCK FileId(1) [12; 73)",
574 "impl Foo {...}",
562 ); 575 );
563 576
564 check_goto( 577 check_goto(
@@ -572,6 +585,7 @@ mod tests {
572 } 585 }
573 ", 586 ",
574 "impl IMPL_BLOCK FileId(1) [12; 73)", 587 "impl IMPL_BLOCK FileId(1) [12; 73)",
588 "impl Foo {...}",
575 ); 589 );
576 590
577 check_goto( 591 check_goto(
@@ -585,6 +599,7 @@ mod tests {
585 } 599 }
586 ", 600 ",
587 "impl IMPL_BLOCK FileId(1) [15; 75)", 601 "impl IMPL_BLOCK FileId(1) [15; 75)",
602 "impl Foo {...}",
588 ); 603 );
589 604
590 check_goto( 605 check_goto(
@@ -597,6 +612,7 @@ mod tests {
597 } 612 }
598 ", 613 ",
599 "impl IMPL_BLOCK FileId(1) [15; 62)", 614 "impl IMPL_BLOCK FileId(1) [15; 62)",
615 "impl Foo {...}",
600 ); 616 );
601 } 617 }
602 618
@@ -616,6 +632,7 @@ mod tests {
616 } 632 }
617 ", 633 ",
618 "impl IMPL_BLOCK FileId(1) [49; 115)", 634 "impl IMPL_BLOCK FileId(1) [49; 115)",
635 "impl Make for Foo {...}",
619 ); 636 );
620 637
621 check_goto( 638 check_goto(
@@ -632,17 +649,19 @@ mod tests {
632 } 649 }
633 ", 650 ",
634 "impl IMPL_BLOCK FileId(1) [49; 115)", 651 "impl IMPL_BLOCK FileId(1) [49; 115)",
652 "impl Make for Foo {...}",
635 ); 653 );
636 } 654 }
637 655
638 #[test] 656 #[test]
639 fn goto_definition_works_when_used_on_definition_name_itself() { 657 fn goto_def_when_used_on_definition_name_itself() {
640 check_goto( 658 check_goto(
641 " 659 "
642 //- /lib.rs 660 //- /lib.rs
643 struct Foo<|> { value: u32 } 661 struct Foo<|> { value: u32 }
644 ", 662 ",
645 "Foo STRUCT_DEF FileId(1) [0; 25) [7; 10)", 663 "Foo STRUCT_DEF FileId(1) [0; 25) [7; 10)",
664 "struct Foo { value: u32 }|Foo",
646 ); 665 );
647 666
648 check_goto( 667 check_goto(
@@ -653,15 +672,16 @@ mod tests {
653 } 672 }
654 "#, 673 "#,
655 "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)", 674 "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)",
675 "field: string|field",
656 ); 676 );
657 677
658 check_goto( 678 check_goto(
659 " 679 "
660 //- /lib.rs 680 //- /lib.rs
661 fn foo_test<|>() { 681 fn foo_test<|>() { }
662 }
663 ", 682 ",
664 "foo_test FN_DEF FileId(1) [0; 17) [3; 11)", 683 "foo_test FN_DEF FileId(1) [0; 17) [3; 11)",
684 "fn foo_test() { }|foo_test",
665 ); 685 );
666 686
667 check_goto( 687 check_goto(
@@ -672,6 +692,7 @@ mod tests {
672 } 692 }
673 ", 693 ",
674 "Foo ENUM_DEF FileId(1) [0; 25) [5; 8)", 694 "Foo ENUM_DEF FileId(1) [0; 25) [5; 8)",
695 "enum Foo {...}|Foo",
675 ); 696 );
676 697
677 check_goto( 698 check_goto(
@@ -684,22 +705,25 @@ mod tests {
684 } 705 }
685 ", 706 ",
686 "Variant2 ENUM_VARIANT FileId(1) [29; 37) [29; 37)", 707 "Variant2 ENUM_VARIANT FileId(1) [29; 37) [29; 37)",
708 "Variant2|Variant2",
687 ); 709 );
688 710
689 check_goto( 711 check_goto(
690 r#" 712 r#"
691 //- /lib.rs 713 //- /lib.rs
692 static inner<|>: &str = ""; 714 static INNER<|>: &str = "";
693 "#, 715 "#,
694 "inner STATIC_DEF FileId(1) [0; 24) [7; 12)", 716 "INNER STATIC_DEF FileId(1) [0; 24) [7; 12)",
717 "static INNER: &str = \"\";|INNER",
695 ); 718 );
696 719
697 check_goto( 720 check_goto(
698 r#" 721 r#"
699 //- /lib.rs 722 //- /lib.rs
700 const inner<|>: &str = ""; 723 const INNER<|>: &str = "";
701 "#, 724 "#,
702 "inner CONST_DEF FileId(1) [0; 23) [6; 11)", 725 "INNER CONST_DEF FileId(1) [0; 23) [6; 11)",
726 "const INNER: &str = \"\";|INNER",
703 ); 727 );
704 728
705 check_goto( 729 check_goto(
@@ -708,24 +732,25 @@ mod tests {
708 type Thing<|> = Option<()>; 732 type Thing<|> = Option<()>;
709 "#, 733 "#,
710 "Thing TYPE_ALIAS_DEF FileId(1) [0; 24) [5; 10)", 734 "Thing TYPE_ALIAS_DEF FileId(1) [0; 24) [5; 10)",
735 "type Thing = Option<()>;|Thing",
711 ); 736 );
712 737
713 check_goto( 738 check_goto(
714 r#" 739 r#"
715 //- /lib.rs 740 //- /lib.rs
716 trait Foo<|> { 741 trait Foo<|> { }
717 }
718 "#, 742 "#,
719 "Foo TRAIT_DEF FileId(1) [0; 13) [6; 9)", 743 "Foo TRAIT_DEF FileId(1) [0; 13) [6; 9)",
744 "trait Foo { }|Foo",
720 ); 745 );
721 746
722 check_goto( 747 check_goto(
723 r#" 748 r#"
724 //- /lib.rs 749 //- /lib.rs
725 mod bar<|> { 750 mod bar<|> { }
726 }
727 "#, 751 "#,
728 "bar MODULE FileId(1) [0; 11) [4; 7)", 752 "bar MODULE FileId(1) [0; 11) [4; 7)",
753 "mod bar { }|bar",
729 ); 754 );
730 } 755 }
731 756
@@ -746,6 +771,7 @@ mod tests {
746 mod confuse_index { fn foo(); } 771 mod confuse_index { fn foo(); }
747 ", 772 ",
748 "foo FN_DEF FileId(1) [52; 63) [55; 58)", 773 "foo FN_DEF FileId(1) [52; 63) [55; 58)",
774 "fn foo() {}|foo",
749 ); 775 );
750 } 776 }
751 777
@@ -774,6 +800,7 @@ mod tests {
774 } 800 }
775 ", 801 ",
776 "foo FN_DEF FileId(1) [398; 415) [401; 404)", 802 "foo FN_DEF FileId(1) [398; 415) [401; 404)",
803 "fn foo() -> i8 {}|foo",
777 ); 804 );
778 } 805 }
779 806
@@ -787,6 +814,82 @@ mod tests {
787 } 814 }
788 ", 815 ",
789 "T TYPE_PARAM FileId(1) [11; 12)", 816 "T TYPE_PARAM FileId(1) [11; 12)",
817 "T",
790 ); 818 );
791 } 819 }
820
821 #[test]
822 fn goto_within_macro() {
823 check_goto(
824 "
825 //- /lib.rs
826 macro_rules! id {
827 ($($tt:tt)*) => ($($tt)*)
828 }
829
830 fn foo() {
831 let x = 1;
832 id!({
833 let y = <|>x;
834 let z = y;
835 });
836 }
837 ",
838 "x BIND_PAT FileId(1) [69; 70)",
839 "x",
840 );
841
842 check_goto(
843 "
844 //- /lib.rs
845 macro_rules! id {
846 ($($tt:tt)*) => ($($tt)*)
847 }
848
849 fn foo() {
850 let x = 1;
851 id!({
852 let y = x;
853 let z = <|>y;
854 });
855 }
856 ",
857 "y BIND_PAT FileId(1) [98; 99)",
858 "y",
859 );
860 }
861
862 #[test]
863 fn goto_def_in_local_fn() {
864 check_goto(
865 "
866 //- /lib.rs
867 fn main() {
868 fn foo() {
869 let x = 92;
870 <|>x;
871 }
872 }
873 ",
874 "x BIND_PAT FileId(1) [39; 40)",
875 "x",
876 );
877 }
878
879 #[test]
880 fn goto_def_for_field_init_shorthand() {
881 covers!(goto_def_for_field_init_shorthand);
882 check_goto(
883 "
884 //- /lib.rs
885 struct Foo { x: i32 }
886 fn main() {
887 let x = 92;
888 Foo { x<|> };
889 }
890 ",
891 "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)",
892 "x: i32|x",
893 )
894 }
792} 895}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 51e320128..a227bf546 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -250,7 +250,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
250 } else { 250 } else {
251 return None; 251 return None;
252 }; 252 };
253 Some(ty.display(db).to_string()) 253 Some(ty.display_truncated(db, None).to_string())
254} 254}
255 255
256#[cfg(test)] 256#[cfg(test)]
@@ -425,6 +425,23 @@ mod tests {
425 } 425 }
426 426
427 #[test] 427 #[test]
428 fn hover_omits_default_generic_types() {
429 check_hover_result(
430 r#"
431//- /main.rs
432struct Test<K, T = u8> {
433 k: K,
434 t: T,
435}
436
437fn main() {
438 let zz<|> = Test { t: 23, k: 33 };
439}"#,
440 &["Test<i32>"],
441 );
442 }
443
444 #[test]
428 fn hover_some() { 445 fn hover_some() {
429 let (analysis, position) = single_file_with_position( 446 let (analysis, position) = single_file_with_position(
430 " 447 "
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 3730121af..3154df457 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -160,6 +160,32 @@ mod tests {
160 use crate::mock_analysis::single_file; 160 use crate::mock_analysis::single_file;
161 161
162 #[test] 162 #[test]
163 fn default_generic_types_should_not_be_displayed() {
164 let (analysis, file_id) = single_file(
165 r#"
166struct Test<K, T = u8> {
167 k: K,
168 t: T,
169}
170
171fn main() {
172 let zz = Test { t: 23, k: 33 };
173}"#,
174 );
175
176 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
177 [
178 InlayHint {
179 range: [69; 71),
180 kind: TypeHint,
181 label: "Test<i32>",
182 },
183 ]
184 "###
185 );
186 }
187
188 #[test]
163 fn let_statement() { 189 fn let_statement() {
164 let (analysis, file_id) = single_file( 190 let (analysis, file_id) = single_file(
165 r#" 191 r#"
diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs
index 848ae4dc7..077a44473 100644
--- a/crates/ra_ide/src/marks.rs
+++ b/crates/ra_ide/src/marks.rs
@@ -3,10 +3,11 @@
3test_utils::marks!( 3test_utils::marks!(
4 inserts_angle_brackets_for_generics 4 inserts_angle_brackets_for_generics
5 inserts_parens_for_function_calls 5 inserts_parens_for_function_calls
6 goto_definition_works_for_macros 6 goto_def_for_macros
7 goto_definition_works_for_methods 7 goto_def_for_methods
8 goto_definition_works_for_fields 8 goto_def_for_fields
9 goto_definition_works_for_record_fields 9 goto_def_for_record_fields
10 goto_def_for_field_init_shorthand
10 call_info_bad_offset 11 call_info_bad_offset
11 dont_complete_current_use 12 dont_complete_current_use
12 dont_complete_primitive_in_use 13 dont_complete_primitive_in_use
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index c1f091ec0..3483a7176 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -134,21 +134,22 @@ pub(crate) fn classify_name_ref(
134 let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); 134 let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None);
135 135
136 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 136 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
137 tested_by!(goto_definition_works_for_methods); 137 tested_by!(goto_def_for_methods);
138 if let Some(func) = analyzer.resolve_method_call(&method_call) { 138 if let Some(func) = analyzer.resolve_method_call(&method_call) {
139 return Some(from_assoc_item(db, func.into())); 139 return Some(from_assoc_item(db, func.into()));
140 } 140 }
141 } 141 }
142 142
143 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 143 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
144 tested_by!(goto_definition_works_for_fields); 144 tested_by!(goto_def_for_fields);
145 if let Some(field) = analyzer.resolve_field(&field_expr) { 145 if let Some(field) = analyzer.resolve_field(&field_expr) {
146 return Some(from_struct_field(db, field)); 146 return Some(from_struct_field(db, field));
147 } 147 }
148 } 148 }
149 149
150 if let Some(record_field) = ast::RecordField::cast(parent.clone()) { 150 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
151 tested_by!(goto_definition_works_for_record_fields); 151 tested_by!(goto_def_for_record_fields);
152 tested_by!(goto_def_for_field_init_shorthand);
152 if let Some(field_def) = analyzer.resolve_record_field(&record_field) { 153 if let Some(field_def) = analyzer.resolve_record_field(&record_field) {
153 return Some(from_struct_field(db, field_def)); 154 return Some(from_struct_field(db, field_def));
154 } 155 }
@@ -160,7 +161,7 @@ pub(crate) fn classify_name_ref(
160 let visibility = None; 161 let visibility = None;
161 162
162 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 163 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
163 tested_by!(goto_definition_works_for_macros); 164 tested_by!(goto_def_for_macros);
164 if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(&macro_call)) { 165 if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(&macro_call)) {
165 let kind = NameKind::Macro(macro_def); 166 let kind = NameKind::Macro(macro_def);
166 return Some(NameDefinition { kind, container, visibility }); 167 return Some(NameDefinition { kind, container, visibility });
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index 2157139f6..a097cf8e8 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
5 5
6.comment { color: #7F9F7F; } 6.comment { color: #7F9F7F; }
7.string { color: #CC9393; } 7.string { color: #CC9393; }
8.field { color: #94BFF3; }
8.function { color: #93E0E3; } 9.function { color: #93E0E3; }
9.parameter { color: #94BFF3; } 10.parameter { color: #94BFF3; }
10.text { color: #DCDCCC; } 11.text { color: #DCDCCC; }
@@ -39,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
39 40
40 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); 41 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>();
41 <span class="keyword.control">if</span> <span class="keyword">true</span> { 42 <span class="keyword.control">if</span> <span class="keyword">true</span> {
42 <span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal.numeric">0</span>, <span class="field">y</span>: <span class="literal.numeric">1</span> }); 43 <span class="keyword">let</span> <span class="variable">x</span> = <span class="literal.numeric">92</span>;
44 <span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="literal.numeric">1</span> });
43 } 45 }
44 <span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal.numeric">0</span>); } 46 <span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal.numeric">0</span>); }
45 47
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html
index 871a52cf6..110556c09 100644
--- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html
+++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html
@@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
5 5
6.comment { color: #7F9F7F; } 6.comment { color: #7F9F7F; }
7.string { color: #CC9393; } 7.string { color: #CC9393; }
8.field { color: #94BFF3; }
8.function { color: #93E0E3; } 9.function { color: #93E0E3; }
9.parameter { color: #94BFF3; } 10.parameter { color: #94BFF3; }
10.text { color: #DCDCCC; } 11.text { color: #DCDCCC; }
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 15e75709c..657c7b21a 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -102,11 +102,10 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
102 COMMENT => tags::LITERAL_COMMENT, 102 COMMENT => tags::LITERAL_COMMENT,
103 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, 103 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING,
104 ATTR => tags::LITERAL_ATTRIBUTE, 104 ATTR => tags::LITERAL_ATTRIBUTE,
105 // Special-case field init shorthand
106 NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => tags::FIELD,
107 NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => continue,
105 NAME_REF => { 108 NAME_REF => {
106 if node.ancestors().any(|it| it.kind() == ATTR) {
107 continue;
108 }
109
110 let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); 109 let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap();
111 let name_kind = 110 let name_kind =
112 classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind); 111 classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind);
@@ -282,6 +281,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
282 281
283.comment { color: #7F9F7F; } 282.comment { color: #7F9F7F; }
284.string { color: #CC9393; } 283.string { color: #CC9393; }
284.field { color: #94BFF3; }
285.function { color: #93E0E3; } 285.function { color: #93E0E3; }
286.parameter { color: #94BFF3; } 286.parameter { color: #94BFF3; }
287.text { color: #DCDCCC; } 287.text { color: #DCDCCC; }
@@ -327,7 +327,8 @@ fn main() {
327 327
328 let mut vec = Vec::new(); 328 let mut vec = Vec::new();
329 if true { 329 if true {
330 vec.push(Foo { x: 0, y: 1 }); 330 let x = 92;
331 vec.push(Foo { x, y: 1 });
331 } 332 }
332 unsafe { vec.set_len(0); } 333 unsafe { vec.set_len(0); }
333 334
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 2c60430d1..ea2cac069 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -476,7 +476,7 @@ impl<'a> TreeSink for TtTreeSink<'a> {
476#[cfg(test)] 476#[cfg(test)]
477mod tests { 477mod tests {
478 use super::*; 478 use super::*;
479 use crate::tests::{create_rules, expand}; 479 use crate::tests::parse_macro;
480 use ra_parser::TokenSource; 480 use ra_parser::TokenSource;
481 use ra_syntax::{ 481 use ra_syntax::{
482 algo::{insert_children, InsertPosition}, 482 algo::{insert_children, InsertPosition},
@@ -485,7 +485,7 @@ mod tests {
485 485
486 #[test] 486 #[test]
487 fn convert_tt_token_source() { 487 fn convert_tt_token_source() {
488 let rules = create_rules( 488 let expansion = parse_macro(
489 r#" 489 r#"
490 macro_rules! literals { 490 macro_rules! literals {
491 ($i:ident) => { 491 ($i:ident) => {
@@ -498,8 +498,8 @@ mod tests {
498 } 498 }
499 } 499 }
500 "#, 500 "#,
501 ); 501 )
502 let expansion = expand(&rules, "literals!(foo);"); 502 .expand_tt("literals!(foo);");
503 let tts = &[expansion.into()]; 503 let tts = &[expansion.into()];
504 let buffer = tt::buffer::TokenBuffer::new(tts); 504 let buffer = tt::buffer::TokenBuffer::new(tts);
505 let mut tt_src = SubtreeTokenSource::new(&buffer); 505 let mut tt_src = SubtreeTokenSource::new(&buffer);
@@ -527,7 +527,7 @@ mod tests {
527 527
528 #[test] 528 #[test]
529 fn stmts_token_trees_to_expr_is_err() { 529 fn stmts_token_trees_to_expr_is_err() {
530 let rules = create_rules( 530 let expansion = parse_macro(
531 r#" 531 r#"
532 macro_rules! stmts { 532 macro_rules! stmts {
533 () => { 533 () => {
@@ -538,8 +538,8 @@ mod tests {
538 } 538 }
539 } 539 }
540 "#, 540 "#,
541 ); 541 )
542 let expansion = expand(&rules, "stmts!();"); 542 .expand_tt("stmts!();");
543 assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); 543 assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err());
544 } 544 }
545 545
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index ff225f0db..e640d115b 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -1,5 +1,7 @@
1use std::fmt::Write;
2
1use ra_parser::FragmentKind; 3use ra_parser::FragmentKind;
2use ra_syntax::{ast, AstNode, NodeOrToken, WalkEvent}; 4use ra_syntax::{ast, AstNode, NodeOrToken, SyntaxKind::IDENT, SyntaxNode, WalkEvent, T};
3use test_utils::assert_eq_text; 5use test_utils::assert_eq_text;
4 6
5use super::*; 7use super::*;
@@ -61,13 +63,14 @@ mod rule_parsing {
61 63
62#[test] 64#[test]
63fn test_token_id_shift() { 65fn test_token_id_shift() {
64 let macro_definition = r#" 66 let expansion = parse_macro(
67 r#"
65macro_rules! foobar { 68macro_rules! foobar {
66 ($e:ident) => { foo bar $e } 69 ($e:ident) => { foo bar $e }
67} 70}
68"#; 71"#,
69 let rules = create_rules(macro_definition); 72 )
70 let expansion = expand(&rules, "foobar!(baz);"); 73 .expand_tt("foobar!(baz);");
71 74
72 fn get_id(t: &tt::TokenTree) -> Option<u32> { 75 fn get_id(t: &tt::TokenTree) -> Option<u32> {
73 if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t { 76 if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t {
@@ -90,22 +93,23 @@ macro_rules! foobar {
90 93
91#[test] 94#[test]
92fn test_token_map() { 95fn test_token_map() {
93 use ra_parser::SyntaxKind::*; 96 let expanded = parse_macro(
94 use ra_syntax::T; 97 r#"
95
96 let macro_definition = r#"
97macro_rules! foobar { 98macro_rules! foobar {
98 ($e:ident) => { fn $e() {} } 99 ($e:ident) => { fn $e() {} }
99} 100}
100"#; 101"#,
101 let rules = create_rules(macro_definition); 102 )
102 let (expansion, (token_map, content)) = expand_and_map(&rules, "foobar!(baz);"); 103 .expand_tt("foobar!(baz);");
104
105 let (node, token_map) = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap();
106 let content = node.syntax_node().to_string();
103 107
104 let get_text = |id, kind| -> String { 108 let get_text = |id, kind| -> String {
105 content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string() 109 content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string()
106 }; 110 };
107 111
108 assert_eq!(expansion.token_trees.len(), 4); 112 assert_eq!(expanded.token_trees.len(), 4);
109 // {($e:ident) => { fn $e() {} }} 113 // {($e:ident) => { fn $e() {} }}
110 // 012345 67 8 9 T12 3 114 // 012345 67 8 9 T12 3
111 115
@@ -116,7 +120,7 @@ macro_rules! foobar {
116 120
117#[test] 121#[test]
118fn test_convert_tt() { 122fn test_convert_tt() {
119 let macro_definition = r#" 123 parse_macro(r#"
120macro_rules! impl_froms { 124macro_rules! impl_froms {
121 ($e:ident: $($v:ident),*) => { 125 ($e:ident: $($v:ident),*) => {
122 $( 126 $(
@@ -128,24 +132,17 @@ macro_rules! impl_froms {
128 )* 132 )*
129 } 133 }
130} 134}
131"#; 135"#)
132 136 .assert_expand_tt(
133 let macro_invocation = r#" 137 "impl_froms!(TokenTree: Leaf, Subtree);",
134impl_froms!(TokenTree: Leaf, Subtree); 138 "impl From <Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \
135"#; 139 impl From <Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}"
136 140 );
137 let rules = create_rules(macro_definition);
138 let expansion = expand(&rules, macro_invocation);
139 assert_eq!(
140 expansion.to_string(),
141 "impl From <Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \
142 impl From <Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}"
143 )
144} 141}
145 142
146#[test] 143#[test]
147fn test_expr_order() { 144fn test_expr_order() {
148 let rules = create_rules( 145 let expanded = parse_macro(
149 r#" 146 r#"
150 macro_rules! foo { 147 macro_rules! foo {
151 ($ i:expr) => { 148 ($ i:expr) => {
@@ -153,11 +150,10 @@ fn test_expr_order() {
153 } 150 }
154 } 151 }
155"#, 152"#,
156 ); 153 )
157 let expanded = expand(&rules, "foo! { 1 + 1}"); 154 .expand_items("foo! { 1 + 1}");
158 let tree = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node();
159 155
160 let dump = format!("{:#?}", tree); 156 let dump = format!("{:#?}", expanded);
161 assert_eq_text!( 157 assert_eq_text!(
162 dump.trim(), 158 dump.trim(),
163 r#"MACRO_ITEMS@[0; 15) 159 r#"MACRO_ITEMS@[0; 15)
@@ -189,7 +185,7 @@ fn test_expr_order() {
189 185
190#[test] 186#[test]
191fn test_fail_match_pattern_by_first_token() { 187fn test_fail_match_pattern_by_first_token() {
192 let rules = create_rules( 188 parse_macro(
193 r#" 189 r#"
194 macro_rules! foo { 190 macro_rules! foo {
195 ($ i:ident) => ( 191 ($ i:ident) => (
@@ -203,16 +199,15 @@ fn test_fail_match_pattern_by_first_token() {
203 ) 199 )
204 } 200 }
205"#, 201"#,
206 ); 202 )
207 203 .assert_expand_items("foo! { foo }", "mod foo {}")
208 assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); 204 .assert_expand_items("foo! { = bar }", "fn bar () {}")
209 assert_expansion(MacroKind::Items, &rules, "foo! { = bar }", "fn bar () {}"); 205 .assert_expand_items("foo! { + Baz }", "struct Baz ;");
210 assert_expansion(MacroKind::Items, &rules, "foo! { + Baz }", "struct Baz ;");
211} 206}
212 207
213#[test] 208#[test]
214fn test_fail_match_pattern_by_last_token() { 209fn test_fail_match_pattern_by_last_token() {
215 let rules = create_rules( 210 parse_macro(
216 r#" 211 r#"
217 macro_rules! foo { 212 macro_rules! foo {
218 ($ i:ident) => ( 213 ($ i:ident) => (
@@ -226,16 +221,15 @@ fn test_fail_match_pattern_by_last_token() {
226 ) 221 )
227 } 222 }
228"#, 223"#,
229 ); 224 )
230 225 .assert_expand_items("foo! { foo }", "mod foo {}")
231 assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); 226 .assert_expand_items("foo! { bar = }", "fn bar () {}")
232 assert_expansion(MacroKind::Items, &rules, "foo! { bar = }", "fn bar () {}"); 227 .assert_expand_items("foo! { Baz + }", "struct Baz ;");
233 assert_expansion(MacroKind::Items, &rules, "foo! { Baz + }", "struct Baz ;");
234} 228}
235 229
236#[test] 230#[test]
237fn test_fail_match_pattern_by_word_token() { 231fn test_fail_match_pattern_by_word_token() {
238 let rules = create_rules( 232 parse_macro(
239 r#" 233 r#"
240 macro_rules! foo { 234 macro_rules! foo {
241 ($ i:ident) => ( 235 ($ i:ident) => (
@@ -249,16 +243,15 @@ fn test_fail_match_pattern_by_word_token() {
249 ) 243 )
250 } 244 }
251"#, 245"#,
252 ); 246 )
253 247 .assert_expand_items("foo! { foo }", "mod foo {}")
254 assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); 248 .assert_expand_items("foo! { spam bar }", "fn bar () {}")
255 assert_expansion(MacroKind::Items, &rules, "foo! { spam bar }", "fn bar () {}"); 249 .assert_expand_items("foo! { eggs Baz }", "struct Baz ;");
256 assert_expansion(MacroKind::Items, &rules, "foo! { eggs Baz }", "struct Baz ;");
257} 250}
258 251
259#[test] 252#[test]
260fn test_match_group_pattern_by_separator_token() { 253fn test_match_group_pattern_by_separator_token() {
261 let rules = create_rules( 254 parse_macro(
262 r#" 255 r#"
263 macro_rules! foo { 256 macro_rules! foo {
264 ($ ($ i:ident),*) => ($ ( 257 ($ ($ i:ident),*) => ($ (
@@ -273,16 +266,15 @@ fn test_match_group_pattern_by_separator_token() {
273 ) 266 )
274 } 267 }
275"#, 268"#,
276 ); 269 )
277 270 .assert_expand_items("foo! { foo, bar }", "mod foo {} mod bar {}")
278 assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "mod foo {} mod bar {}"); 271 .assert_expand_items("foo! { foo# bar }", "fn foo () {} fn bar () {}")
279 assert_expansion(MacroKind::Items, &rules, "foo! { foo# bar }", "fn foo () {} fn bar () {}"); 272 .assert_expand_items("foo! { Foo,# Bar }", "struct Foo ; struct Bar ;");
280 assert_expansion(MacroKind::Items, &rules, "foo! { Foo,# Bar }", "struct Foo ; struct Bar ;");
281} 273}
282 274
283#[test] 275#[test]
284fn test_match_group_pattern_with_multiple_defs() { 276fn test_match_group_pattern_with_multiple_defs() {
285 let rules = create_rules( 277 parse_macro(
286 r#" 278 r#"
287 macro_rules! foo { 279 macro_rules! foo {
288 ($ ($ i:ident),*) => ( struct Bar { $ ( 280 ($ ($ i:ident),*) => ( struct Bar { $ (
@@ -290,19 +282,13 @@ fn test_match_group_pattern_with_multiple_defs() {
290 )*} ); 282 )*} );
291 } 283 }
292"#, 284"#,
293 ); 285 )
294 286 .assert_expand_items("foo! { foo, bar }", "struct Bar {fn foo {} fn bar {}}");
295 assert_expansion(
296 MacroKind::Items,
297 &rules,
298 "foo! { foo, bar }",
299 "struct Bar {fn foo {} fn bar {}}",
300 );
301} 287}
302 288
303#[test] 289#[test]
304fn test_match_group_pattern_with_multiple_statement() { 290fn test_match_group_pattern_with_multiple_statement() {
305 let rules = create_rules( 291 parse_macro(
306 r#" 292 r#"
307 macro_rules! foo { 293 macro_rules! foo {
308 ($ ($ i:ident),*) => ( fn baz { $ ( 294 ($ ($ i:ident),*) => ( fn baz { $ (
@@ -310,14 +296,13 @@ fn test_match_group_pattern_with_multiple_statement() {
310 )*} ); 296 )*} );
311 } 297 }
312"#, 298"#,
313 ); 299 )
314 300 .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ; bar () ;}");
315 assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "fn baz {foo () ; bar () ;}");
316} 301}
317 302
318#[test] 303#[test]
319fn test_match_group_pattern_with_multiple_statement_without_semi() { 304fn test_match_group_pattern_with_multiple_statement_without_semi() {
320 let rules = create_rules( 305 parse_macro(
321 r#" 306 r#"
322 macro_rules! foo { 307 macro_rules! foo {
323 ($ ($ i:ident),*) => ( fn baz { $ ( 308 ($ ($ i:ident),*) => ( fn baz { $ (
@@ -325,14 +310,13 @@ fn test_match_group_pattern_with_multiple_statement_without_semi() {
325 );*} ); 310 );*} );
326 } 311 }
327"#, 312"#,
328 ); 313 )
329 314 .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ;bar ()}");
330 assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "fn baz {foo () ;bar ()}");
331} 315}
332 316
333#[test] 317#[test]
334fn test_match_group_empty_fixed_token() { 318fn test_match_group_empty_fixed_token() {
335 let rules = create_rules( 319 parse_macro(
336 r#" 320 r#"
337 macro_rules! foo { 321 macro_rules! foo {
338 ($ ($ i:ident)* #abc) => ( fn baz { $ ( 322 ($ ($ i:ident)* #abc) => ( fn baz { $ (
@@ -340,69 +324,59 @@ fn test_match_group_empty_fixed_token() {
340 )*} ); 324 )*} );
341 } 325 }
342"#, 326"#,
343 ); 327 )
344 328 .assert_expand_items("foo! {#abc}", "fn baz {}");
345 assert_expansion(MacroKind::Items, &rules, "foo! {#abc}", "fn baz {}");
346} 329}
347 330
348#[test] 331#[test]
349fn test_match_group_in_subtree() { 332fn test_match_group_in_subtree() {
350 let rules = create_rules( 333 parse_macro(
351 r#" 334 r#"
352 macro_rules! foo { 335 macro_rules! foo {
353 (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ ( 336 (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ (
354 $ i (); 337 $ i ();
355 )*} ); 338 )*} );
356 }"#, 339 }"#,
357 ); 340 )
358 341 .assert_expand_items("foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}");
359 assert_expansion(MacroKind::Items, &rules, "foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}");
360} 342}
361 343
362#[test] 344#[test]
363fn test_match_group_with_multichar_sep() { 345fn test_match_group_with_multichar_sep() {
364 let rules = create_rules( 346 parse_macro(
365 r#" 347 r#"
366 macro_rules! foo { 348 macro_rules! foo {
367 (fn $name:ident {$($i:literal)*} ) => ( fn $name() -> bool { $($i)&&*} ); 349 (fn $name:ident {$($i:literal)*} ) => ( fn $name() -> bool { $($i)&&*} );
368 }"#, 350 }"#,
369 ); 351 )
370 352 .assert_expand_items("foo! (fn baz {true true} );", "fn baz () -> bool {true &&true}");
371 assert_expansion(
372 MacroKind::Items,
373 &rules,
374 "foo! (fn baz {true true} );",
375 "fn baz () -> bool {true &&true}",
376 );
377} 353}
378 354
379#[test] 355#[test]
380fn test_match_group_zero_match() { 356fn test_match_group_zero_match() {
381 let rules = create_rules( 357 parse_macro(
382 r#" 358 r#"
383 macro_rules! foo { 359 macro_rules! foo {
384 ( $($i:ident)* ) => (); 360 ( $($i:ident)* ) => ();
385 }"#, 361 }"#,
386 ); 362 )
387 363 .assert_expand_items("foo! ();", "");
388 assert_expansion(MacroKind::Items, &rules, "foo! ();", "");
389} 364}
390 365
391#[test] 366#[test]
392fn test_match_group_in_group() { 367fn test_match_group_in_group() {
393 let rules = create_rules( 368 parse_macro(
394 r#" 369 r#"
395 macro_rules! foo { 370 macro_rules! foo {
396 { $( ( $($i:ident)* ) )* } => ( $( ( $($i)* ) )* ); 371 { $( ( $($i:ident)* ) )* } => ( $( ( $($i)* ) )* );
397 }"#, 372 }"#,
398 ); 373 )
399 374 .assert_expand_items("foo! ( (a b) );", "(a b)");
400 assert_expansion(MacroKind::Items, &rules, "foo! ( (a b) );", "(a b)");
401} 375}
402 376
403#[test] 377#[test]
404fn test_expand_to_item_list() { 378fn test_expand_to_item_list() {
405 let rules = create_rules( 379 let tree = parse_macro(
406 " 380 "
407 macro_rules! structs { 381 macro_rules! structs {
408 ($($i:ident),*) => { 382 ($($i:ident),*) => {
@@ -410,9 +384,8 @@ fn test_expand_to_item_list() {
410 } 384 }
411 } 385 }
412 ", 386 ",
413 ); 387 )
414 let expansion = expand(&rules, "structs!(Foo, Bar);"); 388 .expand_items("structs!(Foo, Bar);");
415 let tree = token_tree_to_syntax_node(&expansion, FragmentKind::Items).unwrap().0.syntax_node();
416 assert_eq!( 389 assert_eq!(
417 format!("{:#?}", tree).trim(), 390 format!("{:#?}", tree).trim(),
418 r#" 391 r#"
@@ -469,7 +442,7 @@ fn test_expand_literals_to_token_tree() {
469 unreachable!("It is not a literal"); 442 unreachable!("It is not a literal");
470 } 443 }
471 444
472 let rules = create_rules( 445 let expansion = parse_macro(
473 r#" 446 r#"
474 macro_rules! literals { 447 macro_rules! literals {
475 ($i:ident) => { 448 ($i:ident) => {
@@ -482,8 +455,8 @@ fn test_expand_literals_to_token_tree() {
482 } 455 }
483 } 456 }
484 "#, 457 "#,
485 ); 458 )
486 let expansion = expand(&rules, "literals!(foo);"); 459 .expand_tt("literals!(foo);");
487 let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees; 460 let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees;
488 461
489 // [let] [a] [=] ['c'] [;] 462 // [let] [a] [=] ['c'] [;]
@@ -498,7 +471,7 @@ fn test_expand_literals_to_token_tree() {
498 471
499#[test] 472#[test]
500fn test_two_idents() { 473fn test_two_idents() {
501 let rules = create_rules( 474 parse_macro(
502 r#" 475 r#"
503 macro_rules! foo { 476 macro_rules! foo {
504 ($ i:ident, $ j:ident) => { 477 ($ i:ident, $ j:ident) => {
@@ -506,18 +479,13 @@ fn test_two_idents() {
506 } 479 }
507 } 480 }
508"#, 481"#,
509 ); 482 )
510 assert_expansion( 483 .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}");
511 MacroKind::Items,
512 &rules,
513 "foo! { foo, bar }",
514 "fn foo () {let a = foo ; let b = bar ;}",
515 );
516} 484}
517 485
518#[test] 486#[test]
519fn test_tt_to_stmts() { 487fn test_tt_to_stmts() {
520 let rules = create_rules( 488 let stmts = parse_macro(
521 r#" 489 r#"
522 macro_rules! foo { 490 macro_rules! foo {
523 () => { 491 () => {
@@ -527,11 +495,8 @@ fn test_tt_to_stmts() {
527 } 495 }
528 } 496 }
529"#, 497"#,
530 ); 498 )
531 499 .expand_statements("foo!{}");
532 let expanded = expand(&rules, "foo!{}");
533 let stmts =
534 token_tree_to_syntax_node(&expanded, FragmentKind::Statements).unwrap().0.syntax_node();
535 500
536 assert_eq!( 501 assert_eq!(
537 format!("{:#?}", stmts).trim(), 502 format!("{:#?}", stmts).trim(),
@@ -571,7 +536,7 @@ fn test_tt_to_stmts() {
571 536
572#[test] 537#[test]
573fn test_match_literal() { 538fn test_match_literal() {
574 let rules = create_rules( 539 parse_macro(
575 r#" 540 r#"
576 macro_rules! foo { 541 macro_rules! foo {
577 ('(') => { 542 ('(') => {
@@ -579,8 +544,8 @@ fn test_match_literal() {
579 } 544 }
580 } 545 }
581"#, 546"#,
582 ); 547 )
583 assert_expansion(MacroKind::Items, &rules, "foo! ['('];", "fn foo () {}"); 548 .assert_expand_items("foo! ['('];", "fn foo () {}");
584} 549}
585 550
586// The following tests are port from intellij-rust directly 551// The following tests are port from intellij-rust directly
@@ -588,7 +553,7 @@ fn test_match_literal() {
588 553
589#[test] 554#[test]
590fn test_path() { 555fn test_path() {
591 let rules = create_rules( 556 parse_macro(
592 r#" 557 r#"
593 macro_rules! foo { 558 macro_rules! foo {
594 ($ i:path) => { 559 ($ i:path) => {
@@ -596,11 +561,9 @@ fn test_path() {
596 } 561 }
597 } 562 }
598"#, 563"#,
599 ); 564 )
600 assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "fn foo () {let a = foo ;}"); 565 .assert_expand_items("foo! { foo }", "fn foo () {let a = foo ;}")
601 assert_expansion( 566 .assert_expand_items(
602 MacroKind::Items,
603 &rules,
604 "foo! { bar::<u8>::baz::<u8> }", 567 "foo! { bar::<u8>::baz::<u8> }",
605 "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}", 568 "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}",
606 ); 569 );
@@ -608,7 +571,7 @@ fn test_path() {
608 571
609#[test] 572#[test]
610fn test_two_paths() { 573fn test_two_paths() {
611 let rules = create_rules( 574 parse_macro(
612 r#" 575 r#"
613 macro_rules! foo { 576 macro_rules! foo {
614 ($ i:path, $ j:path) => { 577 ($ i:path, $ j:path) => {
@@ -616,18 +579,13 @@ fn test_two_paths() {
616 } 579 }
617 } 580 }
618"#, 581"#,
619 ); 582 )
620 assert_expansion( 583 .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}");
621 MacroKind::Items,
622 &rules,
623 "foo! { foo, bar }",
624 "fn foo () {let a = foo ; let b = bar ;}",
625 );
626} 584}
627 585
628#[test] 586#[test]
629fn test_path_with_path() { 587fn test_path_with_path() {
630 let rules = create_rules( 588 parse_macro(
631 r#" 589 r#"
632 macro_rules! foo { 590 macro_rules! foo {
633 ($ i:path) => { 591 ($ i:path) => {
@@ -635,13 +593,13 @@ fn test_path_with_path() {
635 } 593 }
636 } 594 }
637"#, 595"#,
638 ); 596 )
639 assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "fn foo () {let a = foo :: bar ;}"); 597 .assert_expand_items("foo! { foo }", "fn foo () {let a = foo :: bar ;}");
640} 598}
641 599
642#[test] 600#[test]
643fn test_expr() { 601fn test_expr() {
644 let rules = create_rules( 602 parse_macro(
645 r#" 603 r#"
646 macro_rules! foo { 604 macro_rules! foo {
647 ($ i:expr) => { 605 ($ i:expr) => {
@@ -649,11 +607,8 @@ fn test_expr() {
649 } 607 }
650 } 608 }
651"#, 609"#,
652 ); 610 )
653 611 .assert_expand_items(
654 assert_expansion(
655 MacroKind::Items,
656 &rules,
657 "foo! { 2 + 2 * baz(3).quux() }", 612 "foo! { 2 + 2 * baz(3).quux() }",
658 "fn bar () {2 + 2 * baz (3) . quux () ;}", 613 "fn bar () {2 + 2 * baz (3) . quux () ;}",
659 ); 614 );
@@ -661,7 +616,7 @@ fn test_expr() {
661 616
662#[test] 617#[test]
663fn test_last_expr() { 618fn test_last_expr() {
664 let rules = create_rules( 619 parse_macro(
665 r#" 620 r#"
666 macro_rules! vec { 621 macro_rules! vec {
667 ($($item:expr),*) => { 622 ($($item:expr),*) => {
@@ -675,10 +630,8 @@ fn test_last_expr() {
675 }; 630 };
676 } 631 }
677"#, 632"#,
678 ); 633 )
679 assert_expansion( 634 .assert_expand_items(
680 MacroKind::Items,
681 &rules,
682 "vec!(1,2,3);", 635 "vec!(1,2,3);",
683 "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}", 636 "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}",
684 ); 637 );
@@ -686,7 +639,7 @@ fn test_last_expr() {
686 639
687#[test] 640#[test]
688fn test_ty() { 641fn test_ty() {
689 let rules = create_rules( 642 parse_macro(
690 r#" 643 r#"
691 macro_rules! foo { 644 macro_rules! foo {
692 ($ i:ty) => ( 645 ($ i:ty) => (
@@ -694,18 +647,13 @@ fn test_ty() {
694 ) 647 )
695 } 648 }
696"#, 649"#,
697 ); 650 )
698 assert_expansion( 651 .assert_expand_items("foo! { Baz<u8> }", "fn bar () -> Baz < u8 > {unimplemented ! ()}");
699 MacroKind::Items,
700 &rules,
701 "foo! { Baz<u8> }",
702 "fn bar () -> Baz < u8 > {unimplemented ! ()}",
703 );
704} 652}
705 653
706#[test] 654#[test]
707fn test_ty_with_complex_type() { 655fn test_ty_with_complex_type() {
708 let rules = create_rules( 656 parse_macro(
709 r#" 657 r#"
710 macro_rules! foo { 658 macro_rules! foo {
711 ($ i:ty) => ( 659 ($ i:ty) => (
@@ -713,20 +661,14 @@ fn test_ty_with_complex_type() {
713 ) 661 )
714 } 662 }
715"#, 663"#,
716 ); 664 )
717
718 // Reference lifetime struct with generic type 665 // Reference lifetime struct with generic type
719 assert_expansion( 666 .assert_expand_items(
720 MacroKind::Items,
721 &rules,
722 "foo! { &'a Baz<u8> }", 667 "foo! { &'a Baz<u8> }",
723 "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}", 668 "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}",
724 ); 669 )
725
726 // extern "Rust" func type 670 // extern "Rust" func type
727 assert_expansion( 671 .assert_expand_items(
728 MacroKind::Items,
729 &rules,
730 r#"foo! { extern "Rust" fn() -> Ret }"#, 672 r#"foo! { extern "Rust" fn() -> Ret }"#,
731 r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#, 673 r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#,
732 ); 674 );
@@ -734,19 +676,19 @@ fn test_ty_with_complex_type() {
734 676
735#[test] 677#[test]
736fn test_pat_() { 678fn test_pat_() {
737 let rules = create_rules( 679 parse_macro(
738 r#" 680 r#"
739 macro_rules! foo { 681 macro_rules! foo {
740 ($ i:pat) => { fn foo() { let $ i; } } 682 ($ i:pat) => { fn foo() { let $ i; } }
741 } 683 }
742"#, 684"#,
743 ); 685 )
744 assert_expansion(MacroKind::Items, &rules, "foo! { (a, b) }", "fn foo () {let (a , b) ;}"); 686 .assert_expand_items("foo! { (a, b) }", "fn foo () {let (a , b) ;}");
745} 687}
746 688
747#[test] 689#[test]
748fn test_stmt() { 690fn test_stmt() {
749 let rules = create_rules( 691 parse_macro(
750 r#" 692 r#"
751 macro_rules! foo { 693 macro_rules! foo {
752 ($ i:stmt) => ( 694 ($ i:stmt) => (
@@ -754,14 +696,14 @@ fn test_stmt() {
754 ) 696 )
755 } 697 }
756"#, 698"#,
757 ); 699 )
758 assert_expansion(MacroKind::Items, &rules, "foo! { 2 }", "fn bar () {2 ;}"); 700 .assert_expand_items("foo! { 2 }", "fn bar () {2 ;}")
759 assert_expansion(MacroKind::Items, &rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); 701 .assert_expand_items("foo! { let a = 0 }", "fn bar () {let a = 0 ;}");
760} 702}
761 703
762#[test] 704#[test]
763fn test_single_item() { 705fn test_single_item() {
764 let rules = create_rules( 706 parse_macro(
765 r#" 707 r#"
766 macro_rules! foo { 708 macro_rules! foo {
767 ($ i:item) => ( 709 ($ i:item) => (
@@ -769,13 +711,13 @@ fn test_single_item() {
769 ) 711 )
770 } 712 }
771"#, 713"#,
772 ); 714 )
773 assert_expansion(MacroKind::Items, &rules, "foo! {mod c {}}", "mod c {}"); 715 .assert_expand_items("foo! {mod c {}}", "mod c {}");
774} 716}
775 717
776#[test] 718#[test]
777fn test_all_items() { 719fn test_all_items() {
778 let rules = create_rules( 720 parse_macro(
779 r#" 721 r#"
780 macro_rules! foo { 722 macro_rules! foo {
781 ($ ($ i:item)*) => ($ ( 723 ($ ($ i:item)*) => ($ (
@@ -783,10 +725,8 @@ fn test_all_items() {
783 )*) 725 )*)
784 } 726 }
785"#, 727"#,
786 ); 728 ).
787 assert_expansion( 729 assert_expand_items(
788 MacroKind::Items,
789 &rules,
790 r#" 730 r#"
791 foo! { 731 foo! {
792 extern crate a; 732 extern crate a;
@@ -810,19 +750,19 @@ fn test_all_items() {
810 750
811#[test] 751#[test]
812fn test_block() { 752fn test_block() {
813 let rules = create_rules( 753 parse_macro(
814 r#" 754 r#"
815 macro_rules! foo { 755 macro_rules! foo {
816 ($ i:block) => { fn foo() $ i } 756 ($ i:block) => { fn foo() $ i }
817 } 757 }
818"#, 758"#,
819 ); 759 )
820 assert_expansion(MacroKind::Stmts, &rules, "foo! { { 1; } }", "fn foo () {1 ;}"); 760 .assert_expand_statements("foo! { { 1; } }", "fn foo () {1 ;}");
821} 761}
822 762
823#[test] 763#[test]
824fn test_meta() { 764fn test_meta() {
825 let rules = create_rules( 765 parse_macro(
826 r#" 766 r#"
827 macro_rules! foo { 767 macro_rules! foo {
828 ($ i:meta) => ( 768 ($ i:meta) => (
@@ -831,10 +771,8 @@ fn test_meta() {
831 ) 771 )
832 } 772 }
833"#, 773"#,
834 ); 774 )
835 assert_expansion( 775 .assert_expand_items(
836 MacroKind::Items,
837 &rules,
838 r#"foo! { cfg(target_os = "windows") }"#, 776 r#"foo! { cfg(target_os = "windows") }"#,
839 r#"# [cfg (target_os = "windows")] fn bar () {}"#, 777 r#"# [cfg (target_os = "windows")] fn bar () {}"#,
840 ); 778 );
@@ -842,7 +780,7 @@ fn test_meta() {
842 780
843#[test] 781#[test]
844fn test_meta_doc_comments() { 782fn test_meta_doc_comments() {
845 let rules = create_rules( 783 parse_macro(
846 r#" 784 r#"
847 macro_rules! foo { 785 macro_rules! foo {
848 ($(#[$ i:meta])+) => ( 786 ($(#[$ i:meta])+) => (
@@ -851,10 +789,8 @@ fn test_meta_doc_comments() {
851 ) 789 )
852 } 790 }
853"#, 791"#,
854 ); 792 ).
855 assert_expansion( 793 assert_expand_items(
856 MacroKind::Items,
857 &rules,
858 r#"foo! { 794 r#"foo! {
859 /// Single Line Doc 1 795 /// Single Line Doc 1
860 /** 796 /**
@@ -867,69 +803,68 @@ fn test_meta_doc_comments() {
867 803
868#[test] 804#[test]
869fn test_tt_block() { 805fn test_tt_block() {
870 let rules = create_rules( 806 parse_macro(
871 r#" 807 r#"
872 macro_rules! foo { 808 macro_rules! foo {
873 ($ i:tt) => { fn foo() $ i } 809 ($ i:tt) => { fn foo() $ i }
874 } 810 }
875 "#, 811 "#,
876 ); 812 )
877 assert_expansion(MacroKind::Items, &rules, r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#); 813 .assert_expand_items(r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#);
878} 814}
879 815
880#[test] 816#[test]
881fn test_tt_group() { 817fn test_tt_group() {
882 let rules = create_rules( 818 parse_macro(
883 r#" 819 r#"
884 macro_rules! foo { 820 macro_rules! foo {
885 ($($ i:tt)*) => { $($ i)* } 821 ($($ i:tt)*) => { $($ i)* }
886 } 822 }
887 "#, 823 "#,
888 ); 824 )
889 assert_expansion(MacroKind::Items, &rules, r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); 825 .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#);
890} 826}
891#[test] 827#[test]
892fn test_lifetime() { 828fn test_lifetime() {
893 let rules = create_rules( 829 parse_macro(
894 r#" 830 r#"
895 macro_rules! foo { 831 macro_rules! foo {
896 ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } } 832 ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } }
897 } 833 }
898"#, 834"#,
899 ); 835 )
900 assert_expansion(MacroKind::Items, &rules, r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#); 836 .assert_expand_items(r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#);
901} 837}
902 838
903#[test] 839#[test]
904fn test_literal() { 840fn test_literal() {
905 let rules = create_rules( 841 parse_macro(
906 r#" 842 r#"
907 macro_rules! foo { 843 macro_rules! foo {
908 ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;}; 844 ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;};
909 } 845 }
910"#, 846"#,
911 ); 847 )
912 assert_expansion(MacroKind::Items, &rules, r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#); 848 .assert_expand_items(r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#);
913} 849}
914 850
915#[test] 851#[test]
916fn test_vis() { 852fn test_vis() {
917 let rules = create_rules( 853 parse_macro(
918 r#" 854 r#"
919 macro_rules! foo { 855 macro_rules! foo {
920 ($ vis:vis $ name:ident) => { $ vis fn $ name() {}}; 856 ($ vis:vis $ name:ident) => { $ vis fn $ name() {}};
921 } 857 }
922"#, 858"#,
923 ); 859 )
924 assert_expansion(MacroKind::Items, &rules, r#"foo!(pub foo);"#, r#"pub fn foo () {}"#); 860 .assert_expand_items(r#"foo!(pub foo);"#, r#"pub fn foo () {}"#)
925 861 // test optional cases
926 // test optional casse 862 .assert_expand_items(r#"foo!(foo);"#, r#"fn foo () {}"#);
927 assert_expansion(MacroKind::Items, &rules, r#"foo!(foo);"#, r#"fn foo () {}"#);
928} 863}
929 864
930#[test] 865#[test]
931fn test_inner_macro_rules() { 866fn test_inner_macro_rules() {
932 let rules = create_rules( 867 parse_macro(
933 r#" 868 r#"
934macro_rules! foo { 869macro_rules! foo {
935 ($a:ident, $b:ident, $c:tt) => { 870 ($a:ident, $b:ident, $c:tt) => {
@@ -945,10 +880,8 @@ macro_rules! foo {
945 } 880 }
946} 881}
947"#, 882"#,
948 ); 883 ).
949 assert_expansion( 884 assert_expand_items(
950 MacroKind::Items,
951 &rules,
952 r#"foo!(x,y, 1);"#, 885 r#"foo!(x,y, 1);"#,
953 r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#, 886 r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#,
954 ); 887 );
@@ -957,7 +890,7 @@ macro_rules! foo {
957// The following tests are based on real world situations 890// The following tests are based on real world situations
958#[test] 891#[test]
959fn test_vec() { 892fn test_vec() {
960 let rules = create_rules( 893 let fixture = parse_macro(
961 r#" 894 r#"
962 macro_rules! vec { 895 macro_rules! vec {
963 ($($item:expr),*) => { 896 ($($item:expr),*) => {
@@ -972,16 +905,14 @@ fn test_vec() {
972} 905}
973"#, 906"#,
974 ); 907 );
975 assert_expansion(MacroKind::Items, &rules, r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#); 908 fixture
976 assert_expansion( 909 .assert_expand_items(r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#)
977 MacroKind::Items, 910 .assert_expand_items(
978 &rules, 911 r#"vec![1u32,2];"#,
979 r#"vec![1u32,2];"#, 912 r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#,
980 r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#, 913 );
981 );
982 914
983 let expansion = expand(&rules, r#"vec![1u32,2];"#); 915 let tree = fixture.expand_expr(r#"vec![1u32,2];"#);
984 let tree = token_tree_to_syntax_node(&expansion, FragmentKind::Expr).unwrap().0.syntax_node();
985 916
986 assert_eq!( 917 assert_eq!(
987 format!("{:#?}", tree).trim(), 918 format!("{:#?}", tree).trim(),
@@ -1055,7 +986,7 @@ fn test_vec() {
1055fn test_winapi_struct() { 986fn test_winapi_struct() {
1056 // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 987 // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366
1057 988
1058 let rules = create_rules( 989 parse_macro(
1059 r#" 990 r#"
1060macro_rules! STRUCT { 991macro_rules! STRUCT {
1061 ($(#[$attrs:meta])* struct $name:ident { 992 ($(#[$attrs:meta])* struct $name:ident {
@@ -1077,17 +1008,19 @@ macro_rules! STRUCT {
1077 ); 1008 );
1078} 1009}
1079"#, 1010"#,
1080 ); 1011 ).
1081 // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs 1012 // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs
1082 assert_expansion(MacroKind::Items, &rules, r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#, 1013 assert_expand_items(r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#,
1083 "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}"); 1014 "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}"
1084 assert_expansion(MacroKind::Items, &rules, r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#, 1015 )
1085 "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}"); 1016 .assert_expand_items(r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#,
1017 "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}"
1018 );
1086} 1019}
1087 1020
1088#[test] 1021#[test]
1089fn test_int_base() { 1022fn test_int_base() {
1090 let rules = create_rules( 1023 parse_macro(
1091 r#" 1024 r#"
1092macro_rules! int_base { 1025macro_rules! int_base {
1093 ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { 1026 ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
@@ -1100,17 +1033,15 @@ macro_rules! int_base {
1100 } 1033 }
1101} 1034}
1102"#, 1035"#,
1103 ); 1036 ).assert_expand_items(r#" int_base!{Binary for isize as usize -> Binary}"#,
1104
1105 assert_expansion(MacroKind::Items, &rules, r#" int_base!{Binary for isize as usize -> Binary}"#,
1106 "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}" 1037 "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}"
1107 ); 1038 );
1108} 1039}
1109 1040
1110#[test] 1041#[test]
1111fn test_generate_pattern_iterators() { 1042fn test_generate_pattern_iterators() {
1112 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs 1043 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs
1113 let rules = create_rules( 1044 parse_macro(
1114 r#" 1045 r#"
1115macro_rules! generate_pattern_iterators { 1046macro_rules! generate_pattern_iterators {
1116 { double ended; with $(#[$common_stability_attribute:meta])*, 1047 { double ended; with $(#[$common_stability_attribute:meta])*,
@@ -1121,11 +1052,7 @@ macro_rules! generate_pattern_iterators {
1121 } 1052 }
1122} 1053}
1123"#, 1054"#,
1124 ); 1055 ).assert_expand_items(
1125
1126 assert_expansion(
1127 MacroKind::Items,
1128 &rules,
1129 r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#, 1056 r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#,
1130 "fn foo () {}", 1057 "fn foo () {}",
1131 ); 1058 );
@@ -1134,7 +1061,7 @@ macro_rules! generate_pattern_iterators {
1134#[test] 1061#[test]
1135fn test_impl_fn_for_zst() { 1062fn test_impl_fn_for_zst() {
1136 // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs 1063 // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs
1137 let rules = create_rules( 1064 parse_macro(
1138 r#" 1065 r#"
1139macro_rules! impl_fn_for_zst { 1066macro_rules! impl_fn_for_zst {
1140 { $( $( #[$attr: meta] )* 1067 { $( $( #[$attr: meta] )*
@@ -1175,9 +1102,7 @@ $body: block; )+
1175} 1102}
1176 } 1103 }
1177"#, 1104"#,
1178 ); 1105 ).assert_expand_items(r#"
1179
1180 assert_expansion(MacroKind::Items, &rules, r#"
1181impl_fn_for_zst ! { 1106impl_fn_for_zst ! {
1182 # [ derive ( Clone ) ] 1107 # [ derive ( Clone ) ]
1183 struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug { 1108 struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug {
@@ -1194,13 +1119,14 @@ impl_fn_for_zst ! {
1194 } ; 1119 } ;
1195 } 1120 }
1196"#, 1121"#,
1197 "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}"); 1122 "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}"
1123 );
1198} 1124}
1199 1125
1200#[test] 1126#[test]
1201fn test_impl_nonzero_fmt() { 1127fn test_impl_nonzero_fmt() {
1202 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12 1128 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12
1203 let rules = create_rules( 1129 parse_macro(
1204 r#" 1130 r#"
1205 macro_rules! impl_nonzero_fmt { 1131 macro_rules! impl_nonzero_fmt {
1206 ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { 1132 ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
@@ -1208,11 +1134,7 @@ fn test_impl_nonzero_fmt() {
1208 } 1134 }
1209 } 1135 }
1210"#, 1136"#,
1211 ); 1137 ).assert_expand_items(
1212
1213 assert_expansion(
1214 MacroKind::Items,
1215 &rules,
1216 r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#, 1138 r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#,
1217 "fn foo () {}", 1139 "fn foo () {}",
1218 ); 1140 );
@@ -1221,7 +1143,7 @@ fn test_impl_nonzero_fmt() {
1221#[test] 1143#[test]
1222fn test_cfg_if_items() { 1144fn test_cfg_if_items() {
1223 // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986 1145 // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986
1224 let rules = create_rules( 1146 parse_macro(
1225 r#" 1147 r#"
1226 macro_rules! __cfg_if_items { 1148 macro_rules! __cfg_if_items {
1227 (($($not:meta,)*) ; ) => {}; 1149 (($($not:meta,)*) ; ) => {};
@@ -1230,11 +1152,7 @@ fn test_cfg_if_items() {
1230 } 1152 }
1231 } 1153 }
1232"#, 1154"#,
1233 ); 1155 ).assert_expand_items(
1234
1235 assert_expansion(
1236 MacroKind::Items,
1237 &rules,
1238 r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#, 1156 r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#,
1239 "__cfg_if_items ! {(rustdoc ,) ;}", 1157 "__cfg_if_items ! {(rustdoc ,) ;}",
1240 ); 1158 );
@@ -1243,7 +1161,7 @@ fn test_cfg_if_items() {
1243#[test] 1161#[test]
1244fn test_cfg_if_main() { 1162fn test_cfg_if_main() {
1245 // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9 1163 // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9
1246 let rules = create_rules( 1164 parse_macro(
1247 r#" 1165 r#"
1248 macro_rules! cfg_if { 1166 macro_rules! cfg_if {
1249 ($( 1167 ($(
@@ -1264,9 +1182,7 @@ fn test_cfg_if_main() {
1264 }; 1182 };
1265 } 1183 }
1266"#, 1184"#,
1267 ); 1185 ).assert_expand_items(r#"
1268
1269 assert_expansion(MacroKind::Items, &rules, r#"
1270cfg_if ! { 1186cfg_if ! {
1271 if # [ cfg ( target_env = "msvc" ) ] { 1187 if # [ cfg ( target_env = "msvc" ) ] {
1272 // no extra unwinder support needed 1188 // no extra unwinder support needed
@@ -1278,11 +1194,8 @@ cfg_if ! {
1278 } 1194 }
1279 } 1195 }
1280"#, 1196"#,
1281 "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}"); 1197 "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}"
1282 1198 ).assert_expand_items(
1283 assert_expansion(
1284 MacroKind::Items,
1285 &rules,
1286 r#" 1199 r#"
1287cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , } 1200cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , }
1288"#, 1201"#,
@@ -1293,7 +1206,7 @@ cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" ,
1293#[test] 1206#[test]
1294fn test_proptest_arbitrary() { 1207fn test_proptest_arbitrary() {
1295 // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16 1208 // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16
1296 let rules = create_rules( 1209 parse_macro(
1297 r#" 1210 r#"
1298macro_rules! arbitrary { 1211macro_rules! arbitrary {
1299 ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; 1212 ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty;
@@ -1308,22 +1221,21 @@ macro_rules! arbitrary {
1308 }; 1221 };
1309 1222
1310}"#, 1223}"#,
1311 ); 1224 ).assert_expand_items(r#"arbitrary ! ( [ A : Arbitrary ]
1312
1313 assert_expansion(MacroKind::Items, &rules, r#"arbitrary ! ( [ A : Arbitrary ]
1314 Vec < A > , 1225 Vec < A > ,
1315 VecStrategy < A :: Strategy > , 1226 VecStrategy < A :: Strategy > ,
1316 RangedParams1 < A :: Parameters > ; 1227 RangedParams1 < A :: Parameters > ;
1317 args => { let product_unpack ! [ range , a ] = args ; vec ( any_with :: < A > ( a ) , range ) } 1228 args => { let product_unpack ! [ range , a ] = args ; vec ( any_with :: < A > ( a ) , range ) }
1318 ) ;"#, 1229 ) ;"#,
1319 "impl <A : Arbitrary > $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}"); 1230 "impl <A : Arbitrary > $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}"
1231 );
1320} 1232}
1321 1233
1322#[test] 1234#[test]
1323fn test_old_ridl() { 1235fn test_old_ridl() {
1324 // This is from winapi 2.8, which do not have a link from github 1236 // This is from winapi 2.8, which do not have a link from github
1325 // 1237 //
1326 let rules = create_rules( 1238 let expanded = parse_macro(
1327 r#" 1239 r#"
1328#[macro_export] 1240#[macro_export]
1329macro_rules! RIDL { 1241macro_rules! RIDL {
@@ -1339,21 +1251,17 @@ macro_rules! RIDL {
1339 } 1251 }
1340 }; 1252 };
1341}"#, 1253}"#,
1342 ); 1254 ).expand_tt(r#"
1255 RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) {
1256 fn GetDataSize(&mut self) -> UINT
1257 }}"#);
1343 1258
1344 let expanded = expand(
1345 &rules,
1346 r#"
1347RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) {
1348 fn GetDataSize(&mut self) -> UINT
1349}}"#,
1350 );
1351 assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}"); 1259 assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}");
1352} 1260}
1353 1261
1354#[test] 1262#[test]
1355fn test_quick_error() { 1263fn test_quick_error() {
1356 let rules = create_rules( 1264 let expanded = parse_macro(
1357 r#" 1265 r#"
1358macro_rules! quick_error { 1266macro_rules! quick_error {
1359 1267
@@ -1376,10 +1284,8 @@ macro_rules! quick_error {
1376 1284
1377} 1285}
1378"#, 1286"#,
1379 ); 1287 )
1380 1288 .expand_tt(
1381 let expanded = expand(
1382 &rules,
1383 r#" 1289 r#"
1384quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ 1290quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [
1385 => One : UNIT [] {} 1291 => One : UNIT [] {}
@@ -1393,7 +1299,7 @@ quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [
1393 1299
1394#[test] 1300#[test]
1395fn test_empty_repeat_vars_in_empty_repeat_vars() { 1301fn test_empty_repeat_vars_in_empty_repeat_vars() {
1396 let rules = create_rules( 1302 parse_macro(
1397 r#" 1303 r#"
1398macro_rules! delegate_impl { 1304macro_rules! delegate_impl {
1399 ([$self_type:ident, $self_wrap:ty, $self_map:ident] 1305 ([$self_type:ident, $self_wrap:ty, $self_map:ident]
@@ -1440,120 +1346,117 @@ macro_rules! delegate_impl {
1440 } 1346 }
1441} 1347}
1442"#, 1348"#,
1443 ); 1349 ).assert_expand_items(
1444
1445 assert_expansion(
1446 MacroKind::Items,
1447 &rules,
1448 r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#, 1350 r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#,
1449 "impl <> Data for & \'a mut G where G : Data {}", 1351 "impl <> Data for & \'a mut G where G : Data {}",
1450 ); 1352 );
1451} 1353}
1452 1354
1453pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { 1355#[test]
1454 let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); 1356fn expr_interpolation() {
1455 let macro_definition = 1357 let expanded = parse_macro(
1456 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 1358 r#"
1359 macro_rules! id {
1360 ($expr:expr) => {
1361 map($expr)
1362 }
1363 }
1364 "#,
1365 )
1366 .expand_expr("id!(x + foo);");
1457 1367
1458 let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 1368 assert_eq!(expanded.to_string(), "map(x+foo)");
1459 crate::MacroRules::parse(&definition_tt).unwrap()
1460} 1369}
1461 1370
1462pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { 1371pub(crate) struct MacroFixture {
1463 let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); 1372 rules: MacroRules,
1464 let macro_invocation = 1373}
1465 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
1466 1374
1467 let (invocation_tt, _) = ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 1375impl MacroFixture {
1376 pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree {
1377 let source_file = ast::SourceFile::parse(invocation).ok().unwrap();
1378 let macro_invocation =
1379 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
1468 1380
1469 rules.expand(&invocation_tt).unwrap() 1381 let (invocation_tt, _) =
1470} 1382 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
1471 1383
1472pub(crate) fn expand_and_map( 1384 self.rules.expand(&invocation_tt).unwrap()
1473 rules: &MacroRules, 1385 }
1474 invocation: &str,
1475) -> (tt::Subtree, (TokenMap, String)) {
1476 let source_file = ast::SourceFile::parse(invocation).ok().unwrap();
1477 let macro_invocation =
1478 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
1479 1386
1480 let (invocation_tt, _) = ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 1387 fn expand_items(&self, invocation: &str) -> SyntaxNode {
1481 let expanded = rules.expand(&invocation_tt).unwrap(); 1388 let expanded = self.expand_tt(invocation);
1389 token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node()
1390 }
1482 1391
1483 let (node, expanded_token_tree) = 1392 fn expand_statements(&self, invocation: &str) -> SyntaxNode {
1484 token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap(); 1393 let expanded = self.expand_tt(invocation);
1394 token_tree_to_syntax_node(&expanded, FragmentKind::Statements).unwrap().0.syntax_node()
1395 }
1485 1396
1486 (expanded, (expanded_token_tree, node.syntax_node().to_string())) 1397 fn expand_expr(&self, invocation: &str) -> SyntaxNode {
1487} 1398 let expanded = self.expand_tt(invocation);
1399 token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node()
1400 }
1488 1401
1489pub(crate) enum MacroKind { 1402 fn assert_expand_tt(&self, invocation: &str, expected: &str) {
1490 Items, 1403 let expansion = self.expand_tt(invocation);
1491 Stmts, 1404 assert_eq!(expansion.to_string(), expected);
1492} 1405 }
1493 1406
1494pub(crate) fn assert_expansion( 1407 fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture {
1495 kind: MacroKind, 1408 self.assert_expansion(FragmentKind::Items, invocation, expected);
1496 rules: &MacroRules, 1409 self
1497 invocation: &str, 1410 }
1498 expected: &str,
1499) -> tt::Subtree {
1500 let expanded = expand(rules, invocation);
1501 assert_eq!(expanded.to_string(), expected);
1502 1411
1503 let expected = expected.replace("$crate", "C_C__C"); 1412 fn assert_expand_statements(&self, invocation: &str, expected: &str) -> &MacroFixture {
1413 self.assert_expansion(FragmentKind::Statements, invocation, expected);
1414 self
1415 }
1504 1416
1505 // wrap the given text to a macro call 1417 fn assert_expansion(&self, kind: FragmentKind, invocation: &str, expected: &str) {
1506 let expected = { 1418 let expanded = self.expand_tt(invocation);
1507 let wrapped = format!("wrap_macro!( {} )", expected); 1419 assert_eq!(expanded.to_string(), expected);
1508 let wrapped = ast::SourceFile::parse(&wrapped); 1420
1509 let wrapped = wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); 1421 let expected = expected.replace("$crate", "C_C__C");
1510 let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; 1422
1511 wrapped.delimiter = None; 1423 // wrap the given text to a macro call
1512 wrapped 1424 let expected = {
1513 }; 1425 let wrapped = format!("wrap_macro!( {} )", expected);
1514 let (expanded_tree, expected_tree) = match kind { 1426 let wrapped = ast::SourceFile::parse(&wrapped);
1515 MacroKind::Items => { 1427 let wrapped =
1516 let expanded_tree = 1428 wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
1517 token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node(); 1429 let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0;
1518 let expected_tree = 1430 wrapped.delimiter = None;
1519 token_tree_to_syntax_node(&expected, FragmentKind::Items).unwrap().0.syntax_node(); 1431 wrapped
1520 1432 };
1521 (
1522 debug_dump_ignore_spaces(&expanded_tree).trim().to_string(),
1523 debug_dump_ignore_spaces(&expected_tree).trim().to_string(),
1524 )
1525 }
1526 1433
1527 MacroKind::Stmts => { 1434 let expanded_tree = token_tree_to_syntax_node(&expanded, kind).unwrap().0.syntax_node();
1528 let expanded_tree = token_tree_to_syntax_node(&expanded, FragmentKind::Statements) 1435 let expanded_tree = debug_dump_ignore_spaces(&expanded_tree).trim().to_string();
1529 .unwrap()
1530 .0
1531 .syntax_node();
1532 let expected_tree = token_tree_to_syntax_node(&expected, FragmentKind::Statements)
1533 .unwrap()
1534 .0
1535 .syntax_node();
1536
1537 (
1538 debug_dump_ignore_spaces(&expanded_tree).trim().to_string(),
1539 debug_dump_ignore_spaces(&expected_tree).trim().to_string(),
1540 )
1541 }
1542 };
1543 1436
1544 let expected_tree = expected_tree.replace("C_C__C", "$crate"); 1437 let expected_tree = token_tree_to_syntax_node(&expected, kind).unwrap().0.syntax_node();
1545 assert_eq!( 1438 let expected_tree = debug_dump_ignore_spaces(&expected_tree).trim().to_string();
1546 expanded_tree, expected_tree,
1547 "\nleft:\n{}\nright:\n{}",
1548 expanded_tree, expected_tree,
1549 );
1550 1439
1551 expanded 1440 let expected_tree = expected_tree.replace("C_C__C", "$crate");
1441 assert_eq!(
1442 expanded_tree, expected_tree,
1443 "\nleft:\n{}\nright:\n{}",
1444 expanded_tree, expected_tree,
1445 );
1446 }
1552} 1447}
1553 1448
1554pub fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { 1449pub(crate) fn parse_macro(macro_definition: &str) -> MacroFixture {
1555 use std::fmt::Write; 1450 let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap();
1451 let macro_definition =
1452 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
1453
1454 let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
1455 let rules = MacroRules::parse(&definition_tt).unwrap();
1456 MacroFixture { rules }
1457}
1556 1458
1459fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String {
1557 let mut level = 0; 1460 let mut level = 0;
1558 let mut buf = String::new(); 1461 let mut buf = String::new();
1559 macro_rules! indent { 1462 macro_rules! indent {
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index 6e9e212b7..22f64a9f4 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -264,7 +264,7 @@ fn name_r(p: &mut Parser, recovery: TokenSet) {
264} 264}
265 265
266fn name(p: &mut Parser) { 266fn name(p: &mut Parser) {
267 name_r(p, TokenSet::empty()) 267 name_r(p, TokenSet::EMPTY)
268} 268}
269 269
270fn name_ref(p: &mut Parser) { 270fn name_ref(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 09f0a2d98..4ac1d6334 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -43,6 +43,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
43 T!['('], 43 T!['('],
44 T!['{'], 44 T!['{'],
45 T!['['], 45 T!['['],
46 L_DOLLAR,
46 T![|], 47 T![|],
47 T![move], 48 T![move],
48 T![box], 49 T![box],
@@ -443,7 +444,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
443 // } 444 // }
444 attributes::outer_attributes(p); 445 attributes::outer_attributes(p);
445 446
446 patterns::pattern_list_r(p, TokenSet::empty()); 447 patterns::pattern_list_r(p, TokenSet::EMPTY);
447 if p.at(T![if]) { 448 if p.at(T![if]) {
448 match_guard(p); 449 match_guard(p);
449 } 450 }
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs
index 45241e566..65134277e 100644
--- a/crates/ra_parser/src/lib.rs
+++ b/crates/ra_parser/src/lib.rs
@@ -83,6 +83,7 @@ pub fn parse(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) {
83 parse_from_tokens(token_source, tree_sink, grammar::root); 83 parse_from_tokens(token_source, tree_sink, grammar::root);
84} 84}
85 85
86#[derive(Clone, Copy)]
86pub enum FragmentKind { 87pub enum FragmentKind {
87 Path, 88 Path,
88 Expr, 89 Expr,
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index dafd5247b..1071c46dc 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -208,7 +208,7 @@ impl<'t> Parser<'t> {
208 208
209 /// Create an error node and consume the next token. 209 /// Create an error node and consume the next token.
210 pub(crate) fn err_and_bump(&mut self, message: &str) { 210 pub(crate) fn err_and_bump(&mut self, message: &str) {
211 self.err_recover(message, TokenSet::empty()); 211 self.err_recover(message, TokenSet::EMPTY);
212 } 212 }
213 213
214 /// Create an error node and consume the next token. 214 /// Create an error node and consume the next token.
diff --git a/crates/ra_parser/src/token_set.rs b/crates/ra_parser/src/token_set.rs
index 2a6952c01..994017acf 100644
--- a/crates/ra_parser/src/token_set.rs
+++ b/crates/ra_parser/src/token_set.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! A bit-set of `SyntaxKind`s.
2 2
3use crate::SyntaxKind; 3use crate::SyntaxKind;
4 4
@@ -7,9 +7,7 @@ use crate::SyntaxKind;
7pub(crate) struct TokenSet(u128); 7pub(crate) struct TokenSet(u128);
8 8
9impl TokenSet { 9impl TokenSet {
10 pub(crate) const fn empty() -> TokenSet { 10 pub(crate) const EMPTY: TokenSet = TokenSet(0);
11 TokenSet(0)
12 }
13 11
14 pub(crate) const fn singleton(kind: SyntaxKind) -> TokenSet { 12 pub(crate) const fn singleton(kind: SyntaxKind) -> TokenSet {
15 TokenSet(mask(kind)) 13 TokenSet(mask(kind))
@@ -30,7 +28,7 @@ const fn mask(kind: SyntaxKind) -> u128 {
30 28
31#[macro_export] 29#[macro_export]
32macro_rules! token_set { 30macro_rules! token_set {
33 ($($t:expr),*) => { TokenSet::empty()$(.union(TokenSet::singleton($t)))* }; 31 ($($t:expr),*) => { TokenSet::EMPTY$(.union(TokenSet::singleton($t)))* };
34 ($($t:expr),* ,) => { token_set!($($t),*) }; 32 ($($t:expr),* ,) => { token_set!($($t),*) };
35} 33}
36 34
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 657ddf2a6..659f77b71 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -207,8 +207,8 @@ pub fn lines_match(expected: &str, actual: &str) -> bool {
207 // Let's not deal with / vs \ (windows...) 207 // Let's not deal with / vs \ (windows...)
208 // First replace backslash-escaped backslashes with forward slashes 208 // First replace backslash-escaped backslashes with forward slashes
209 // which can occur in, for example, JSON output 209 // which can occur in, for example, JSON output
210 let expected = expected.replace("\\\\", "/").replace("\\", "/"); 210 let expected = expected.replace(r"\\", "/").replace(r"\", "/");
211 let mut actual: &str = &actual.replace("\\\\", "/").replace("\\", "/"); 211 let mut actual: &str = &actual.replace(r"\\", "/").replace(r"\", "/");
212 for (i, part) in expected.split("[..]").enumerate() { 212 for (i, part) in expected.split("[..]").enumerate() {
213 match actual.find(part) { 213 match actual.find(part) {
214 Some(j) => { 214 Some(j) => {