diff options
author | Zac Pullar-Strecker <[email protected]> | 2020-07-31 03:12:44 +0100 |
---|---|---|
committer | Zac Pullar-Strecker <[email protected]> | 2020-07-31 03:12:44 +0100 |
commit | f05d7b41a719d848844b054a16477b29d0f063c6 (patch) | |
tree | 0a8a0946e8aef2ce64d4c13d0035ba41cce2daf3 /crates/ra_hir_def/src | |
parent | 73ff610e41959e3e7c78a2b4b25b086883132956 (diff) | |
parent | 6b7cb8b5ab539fc4333ce34bc29bf77c976f232a (diff) |
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Hasn't fixed tests yet.
Diffstat (limited to 'crates/ra_hir_def/src')
30 files changed, 2938 insertions, 2591 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 4994a2125..6cb56a1cd 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -8,7 +8,7 @@ use hir_expand::{ | |||
8 | InFile, | 8 | InFile, |
9 | }; | 9 | }; |
10 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::{map::ArenaMap, Arena}; |
11 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; | 11 | use ra_syntax::ast::{self, NameOwner, VisibilityOwner}; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | body::{CfgExpander, LowerCtx}, | 14 | body::{CfgExpander, LowerCtx}, |
@@ -112,7 +112,7 @@ impl EnumData { | |||
112 | 112 | ||
113 | impl HasChildSource for EnumId { | 113 | impl HasChildSource for EnumId { |
114 | type ChildId = LocalEnumVariantId; | 114 | type ChildId = LocalEnumVariantId; |
115 | type Value = ast::EnumVariant; | 115 | type Value = ast::Variant; |
116 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { | 116 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { |
117 | let src = self.lookup(db).source(db); | 117 | let src = self.lookup(db).source(db); |
118 | let mut trace = Trace::new_for_map(); | 118 | let mut trace = Trace::new_for_map(); |
@@ -123,8 +123,8 @@ impl HasChildSource for EnumId { | |||
123 | 123 | ||
124 | fn lower_enum( | 124 | fn lower_enum( |
125 | db: &dyn DefDatabase, | 125 | db: &dyn DefDatabase, |
126 | trace: &mut Trace<EnumVariantData, ast::EnumVariant>, | 126 | trace: &mut Trace<EnumVariantData, ast::Variant>, |
127 | ast: &InFile<ast::EnumDef>, | 127 | ast: &InFile<ast::Enum>, |
128 | module_id: ModuleId, | 128 | module_id: ModuleId, |
129 | ) { | 129 | ) { |
130 | let expander = CfgExpander::new(db, ast.file_id, module_id.krate); | 130 | let expander = CfgExpander::new(db, ast.file_id, module_id.krate); |
@@ -179,7 +179,7 @@ impl VariantData { | |||
179 | 179 | ||
180 | impl HasChildSource for VariantId { | 180 | impl HasChildSource for VariantId { |
181 | type ChildId = LocalFieldId; | 181 | type ChildId = LocalFieldId; |
182 | type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>; | 182 | type Value = Either<ast::TupleField, ast::RecordField>; |
183 | 183 | ||
184 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { | 184 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { |
185 | let (src, module_id) = match self { | 185 | let (src, module_id) = match self { |
@@ -194,7 +194,7 @@ impl HasChildSource for VariantId { | |||
194 | } | 194 | } |
195 | VariantId::UnionId(it) => ( | 195 | VariantId::UnionId(it) => ( |
196 | it.lookup(db).source(db).map(|it| { | 196 | it.lookup(db).source(db).map(|it| { |
197 | it.record_field_def_list() | 197 | it.record_field_list() |
198 | .map(ast::StructKind::Record) | 198 | .map(ast::StructKind::Record) |
199 | .unwrap_or(ast::StructKind::Unit) | 199 | .unwrap_or(ast::StructKind::Unit) |
200 | }), | 200 | }), |
@@ -218,7 +218,7 @@ pub enum StructKind { | |||
218 | fn lower_struct( | 218 | fn lower_struct( |
219 | db: &dyn DefDatabase, | 219 | db: &dyn DefDatabase, |
220 | expander: &mut CfgExpander, | 220 | expander: &mut CfgExpander, |
221 | trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, | 221 | trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>, |
222 | ast: &InFile<ast::StructKind>, | 222 | ast: &InFile<ast::StructKind>, |
223 | ) -> StructKind { | 223 | ) -> StructKind { |
224 | let ctx = LowerCtx::new(db, ast.file_id); | 224 | let ctx = LowerCtx::new(db, ast.file_id); |
@@ -234,7 +234,7 @@ fn lower_struct( | |||
234 | || Either::Left(fd.clone()), | 234 | || Either::Left(fd.clone()), |
235 | || FieldData { | 235 | || FieldData { |
236 | name: Name::new_tuple_field(i), | 236 | name: Name::new_tuple_field(i), |
237 | type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()), | 237 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), |
238 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 238 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
239 | }, | 239 | }, |
240 | ); | 240 | ); |
@@ -251,7 +251,7 @@ fn lower_struct( | |||
251 | || Either::Right(fd.clone()), | 251 | || Either::Right(fd.clone()), |
252 | || FieldData { | 252 | || FieldData { |
253 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | 253 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), |
254 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()), | 254 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), |
255 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 255 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
256 | }, | 256 | }, |
257 | ); | 257 | ); |
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index e228e2145..050832ce0 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs | |||
@@ -5,7 +5,7 @@ use std::{ops, sync::Arc}; | |||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; | 6 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; |
7 | use mbe::ast_to_token_tree; | 7 | use mbe::ast_to_token_tree; |
8 | use ra_cfg::CfgOptions; | 8 | use ra_cfg::{CfgExpr, CfgOptions}; |
9 | use ra_syntax::{ | 9 | use ra_syntax::{ |
10 | ast::{self, AstNode, AttrsOwner}, | 10 | ast::{self, AstNode, AttrsOwner}, |
11 | SmolStr, | 11 | SmolStr, |
@@ -125,9 +125,12 @@ impl Attrs { | |||
125 | AttrQuery { attrs: self, key } | 125 | AttrQuery { attrs: self, key } |
126 | } | 126 | } |
127 | 127 | ||
128 | pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { | 128 | pub fn cfg(&self) -> impl Iterator<Item = CfgExpr> + '_ { |
129 | // FIXME: handle cfg_attr :-) | 129 | // FIXME: handle cfg_attr :-) |
130 | self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) | 130 | self.by_key("cfg").tt_values().map(CfgExpr::parse) |
131 | } | ||
132 | pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { | ||
133 | self.cfg().all(|cfg| cfg_options.check(&cfg) != Some(false)) | ||
131 | } | 134 | } |
132 | } | 135 | } |
133 | 136 | ||
@@ -148,18 +151,15 @@ pub enum AttrInput { | |||
148 | impl Attr { | 151 | impl Attr { |
149 | fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { | 152 | fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { |
150 | let path = ModPath::from_src(ast.path()?, hygiene)?; | 153 | let path = ModPath::from_src(ast.path()?, hygiene)?; |
151 | let input = match ast.input() { | 154 | let input = if let Some(lit) = ast.literal() { |
152 | None => None, | 155 | // FIXME: escape? raw string? |
153 | Some(ast::AttrInput::Literal(lit)) => { | 156 | let value = lit.syntax().first_token()?.text().trim_matches('"').into(); |
154 | // FIXME: escape? raw string? | 157 | Some(AttrInput::Literal(value)) |
155 | let value = lit.syntax().first_token()?.text().trim_matches('"').into(); | 158 | } else if let Some(tt) = ast.token_tree() { |
156 | Some(AttrInput::Literal(value)) | 159 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) |
157 | } | 160 | } else { |
158 | Some(ast::AttrInput::TokenTree(tt)) => { | 161 | None |
159 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) | ||
160 | } | ||
161 | }; | 162 | }; |
162 | |||
163 | Some(Attr { path, input }) | 163 | Some(Attr { path, input }) |
164 | } | 164 | } |
165 | } | 165 | } |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 4f2350915..d5f18b920 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -14,6 +14,7 @@ use ra_db::CrateId; | |||
14 | use ra_prof::profile; | 14 | use ra_prof::profile; |
15 | use ra_syntax::{ast, AstNode, AstPtr}; | 15 | use ra_syntax::{ast, AstNode, AstPtr}; |
16 | use rustc_hash::FxHashMap; | 16 | use rustc_hash::FxHashMap; |
17 | use test_utils::mark; | ||
17 | 18 | ||
18 | pub(crate) use lower::LowerCtx; | 19 | pub(crate) use lower::LowerCtx; |
19 | 20 | ||
@@ -42,9 +43,15 @@ pub(crate) struct Expander { | |||
42 | current_file_id: HirFileId, | 43 | current_file_id: HirFileId, |
43 | ast_id_map: Arc<AstIdMap>, | 44 | ast_id_map: Arc<AstIdMap>, |
44 | module: ModuleId, | 45 | module: ModuleId, |
45 | recursive_limit: usize, | 46 | recursion_limit: usize, |
46 | } | 47 | } |
47 | 48 | ||
49 | #[cfg(test)] | ||
50 | const EXPANSION_RECURSION_LIMIT: usize = 32; | ||
51 | |||
52 | #[cfg(not(test))] | ||
53 | const EXPANSION_RECURSION_LIMIT: usize = 128; | ||
54 | |||
48 | impl CfgExpander { | 55 | impl CfgExpander { |
49 | pub(crate) fn new( | 56 | pub(crate) fn new( |
50 | db: &dyn DefDatabase, | 57 | db: &dyn DefDatabase, |
@@ -81,7 +88,7 @@ impl Expander { | |||
81 | current_file_id, | 88 | current_file_id, |
82 | ast_id_map, | 89 | ast_id_map, |
83 | module, | 90 | module, |
84 | recursive_limit: 0, | 91 | recursion_limit: 0, |
85 | } | 92 | } |
86 | } | 93 | } |
87 | 94 | ||
@@ -91,7 +98,9 @@ impl Expander { | |||
91 | local_scope: Option<&ItemScope>, | 98 | local_scope: Option<&ItemScope>, |
92 | macro_call: ast::MacroCall, | 99 | macro_call: ast::MacroCall, |
93 | ) -> Option<(Mark, T)> { | 100 | ) -> Option<(Mark, T)> { |
94 | if self.recursive_limit > 1024 { | 101 | self.recursion_limit += 1; |
102 | if self.recursion_limit > EXPANSION_RECURSION_LIMIT { | ||
103 | mark::hit!(your_stack_belongs_to_me); | ||
95 | return None; | 104 | return None; |
96 | } | 105 | } |
97 | 106 | ||
@@ -118,8 +127,6 @@ impl Expander { | |||
118 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); | 127 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); |
119 | self.current_file_id = file_id; | 128 | self.current_file_id = file_id; |
120 | self.ast_id_map = db.ast_id_map(file_id); | 129 | self.ast_id_map = db.ast_id_map(file_id); |
121 | self.recursive_limit += 1; | ||
122 | |||
123 | return Some((mark, expr)); | 130 | return Some((mark, expr)); |
124 | } | 131 | } |
125 | } | 132 | } |
@@ -134,7 +141,7 @@ impl Expander { | |||
134 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); | 141 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); |
135 | self.current_file_id = mark.file_id; | 142 | self.current_file_id = mark.file_id; |
136 | self.ast_id_map = mem::take(&mut mark.ast_id_map); | 143 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
137 | self.recursive_limit -= 1; | 144 | self.recursion_limit -= 1; |
138 | mark.bomb.defuse(); | 145 | mark.bomb.defuse(); |
139 | } | 146 | } |
140 | 147 | ||
@@ -209,7 +216,7 @@ pub struct BodySourceMap { | |||
209 | expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, | 216 | expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, |
210 | pat_map: FxHashMap<PatSource, PatId>, | 217 | pat_map: FxHashMap<PatSource, PatId>, |
211 | pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, | 218 | pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, |
212 | field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordField>>>, | 219 | field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>, |
213 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, | 220 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, |
214 | } | 221 | } |
215 | 222 | ||
@@ -302,7 +309,53 @@ impl BodySourceMap { | |||
302 | self.pat_map.get(&src).cloned() | 309 | self.pat_map.get(&src).cloned() |
303 | } | 310 | } |
304 | 311 | ||
305 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordField>> { | 312 | pub fn node_self_param(&self, node: InFile<&ast::SelfParam>) -> Option<PatId> { |
313 | let src = node.map(|it| Either::Right(AstPtr::new(it))); | ||
314 | self.pat_map.get(&src).cloned() | ||
315 | } | ||
316 | |||
317 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> { | ||
306 | self.field_map[&(expr, field)].clone() | 318 | self.field_map[&(expr, field)].clone() |
307 | } | 319 | } |
308 | } | 320 | } |
321 | |||
322 | #[cfg(test)] | ||
323 | mod tests { | ||
324 | use ra_db::{fixture::WithFixture, SourceDatabase}; | ||
325 | use test_utils::mark; | ||
326 | |||
327 | use crate::ModuleDefId; | ||
328 | |||
329 | use super::*; | ||
330 | |||
331 | fn lower(ra_fixture: &str) -> Arc<Body> { | ||
332 | let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture); | ||
333 | |||
334 | let krate = db.crate_graph().iter().next().unwrap(); | ||
335 | let def_map = db.crate_def_map(krate); | ||
336 | let module = def_map.modules_for_file(file_id).next().unwrap(); | ||
337 | let module = &def_map[module]; | ||
338 | let fn_def = match module.scope.declarations().next().unwrap() { | ||
339 | ModuleDefId::FunctionId(it) => it, | ||
340 | _ => panic!(), | ||
341 | }; | ||
342 | |||
343 | db.body(fn_def.into()) | ||
344 | } | ||
345 | |||
346 | #[test] | ||
347 | fn your_stack_belongs_to_me() { | ||
348 | mark::check!(your_stack_belongs_to_me); | ||
349 | lower( | ||
350 | " | ||
351 | macro_rules! n_nuple { | ||
352 | ($e:tt) => (); | ||
353 | ($($rest:tt)*) => {{ | ||
354 | (n_nuple!($($rest)*)None,) | ||
355 | }}; | ||
356 | } | ||
357 | fn main() { n_nuple!(1,2,3); } | ||
358 | ", | ||
359 | ); | ||
360 | } | ||
361 | } | ||
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index c6bc85e2f..827ced4ad 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -11,7 +11,7 @@ use ra_arena::Arena; | |||
11 | use ra_syntax::{ | 11 | use ra_syntax::{ |
12 | ast::{ | 12 | ast::{ |
13 | self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, | 13 | self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, |
14 | SlicePatComponents, TypeAscriptionOwner, | 14 | SlicePatComponents, |
15 | }, | 15 | }, |
16 | AstNode, AstPtr, | 16 | AstNode, AstPtr, |
17 | }; | 17 | }; |
@@ -379,10 +379,10 @@ impl ExprCollector<'_> { | |||
379 | let expr = e.expr().map(|e| self.collect_expr(e)); | 379 | let expr = e.expr().map(|e| self.collect_expr(e)); |
380 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) | 380 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) |
381 | } | 381 | } |
382 | ast::Expr::RecordLit(e) => { | 382 | ast::Expr::RecordExpr(e) => { |
383 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 383 | let path = e.path().and_then(|path| self.expander.parse_path(path)); |
384 | let mut field_ptrs = Vec::new(); | 384 | let mut field_ptrs = Vec::new(); |
385 | let record_lit = if let Some(nfl) = e.record_field_list() { | 385 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { |
386 | let fields = nfl | 386 | let fields = nfl |
387 | .fields() | 387 | .fields() |
388 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 388 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
@@ -432,7 +432,7 @@ impl ExprCollector<'_> { | |||
432 | } | 432 | } |
433 | ast::Expr::CastExpr(e) => { | 433 | ast::Expr::CastExpr(e) => { |
434 | let expr = self.collect_expr_opt(e.expr()); | 434 | let expr = self.collect_expr_opt(e.expr()); |
435 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref()); | 435 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); |
436 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 436 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
437 | } | 437 | } |
438 | ast::Expr::RefExpr(e) => { | 438 | ast::Expr::RefExpr(e) => { |
@@ -466,16 +466,13 @@ impl ExprCollector<'_> { | |||
466 | if let Some(pl) = e.param_list() { | 466 | if let Some(pl) = e.param_list() { |
467 | for param in pl.params() { | 467 | for param in pl.params() { |
468 | let pat = self.collect_pat_opt(param.pat()); | 468 | let pat = self.collect_pat_opt(param.pat()); |
469 | let type_ref = | 469 | let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); |
470 | param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); | ||
471 | args.push(pat); | 470 | args.push(pat); |
472 | arg_types.push(type_ref); | 471 | arg_types.push(type_ref); |
473 | } | 472 | } |
474 | } | 473 | } |
475 | let ret_type = e | 474 | let ret_type = |
476 | .ret_type() | 475 | e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); |
477 | .and_then(|r| r.type_ref()) | ||
478 | .map(|it| TypeRef::from_ast(&self.ctx(), it)); | ||
479 | let body = self.collect_expr_opt(e.body()); | 476 | let body = self.collect_expr_opt(e.body()); |
480 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 477 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
481 | } | 478 | } |
@@ -607,8 +604,7 @@ impl ExprCollector<'_> { | |||
607 | .map(|s| match s { | 604 | .map(|s| match s { |
608 | ast::Stmt::LetStmt(stmt) => { | 605 | ast::Stmt::LetStmt(stmt) => { |
609 | let pat = self.collect_pat_opt(stmt.pat()); | 606 | let pat = self.collect_pat_opt(stmt.pat()); |
610 | let type_ref = | 607 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); |
611 | stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); | ||
612 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 608 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
613 | Statement::Let { pat, type_ref, initializer } | 609 | Statement::Let { pat, type_ref, initializer } |
614 | } | 610 | } |
@@ -627,53 +623,53 @@ impl ExprCollector<'_> { | |||
627 | .items() | 623 | .items() |
628 | .filter_map(|item| { | 624 | .filter_map(|item| { |
629 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { | 625 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { |
630 | ast::ModuleItem::FnDef(def) => { | 626 | ast::Item::Fn(def) => { |
631 | let id = self.find_inner_item(&def)?; | 627 | let id = self.find_inner_item(&def)?; |
632 | ( | 628 | ( |
633 | FunctionLoc { container: container.into(), id }.intern(self.db).into(), | 629 | FunctionLoc { container: container.into(), id }.intern(self.db).into(), |
634 | def.name(), | 630 | def.name(), |
635 | ) | 631 | ) |
636 | } | 632 | } |
637 | ast::ModuleItem::TypeAliasDef(def) => { | 633 | ast::Item::TypeAlias(def) => { |
638 | let id = self.find_inner_item(&def)?; | 634 | let id = self.find_inner_item(&def)?; |
639 | ( | 635 | ( |
640 | TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), | 636 | TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), |
641 | def.name(), | 637 | def.name(), |
642 | ) | 638 | ) |
643 | } | 639 | } |
644 | ast::ModuleItem::ConstDef(def) => { | 640 | ast::Item::Const(def) => { |
645 | let id = self.find_inner_item(&def)?; | 641 | let id = self.find_inner_item(&def)?; |
646 | ( | 642 | ( |
647 | ConstLoc { container: container.into(), id }.intern(self.db).into(), | 643 | ConstLoc { container: container.into(), id }.intern(self.db).into(), |
648 | def.name(), | 644 | def.name(), |
649 | ) | 645 | ) |
650 | } | 646 | } |
651 | ast::ModuleItem::StaticDef(def) => { | 647 | ast::Item::Static(def) => { |
652 | let id = self.find_inner_item(&def)?; | 648 | let id = self.find_inner_item(&def)?; |
653 | (StaticLoc { container, id }.intern(self.db).into(), def.name()) | 649 | (StaticLoc { container, id }.intern(self.db).into(), def.name()) |
654 | } | 650 | } |
655 | ast::ModuleItem::StructDef(def) => { | 651 | ast::Item::Struct(def) => { |
656 | let id = self.find_inner_item(&def)?; | 652 | let id = self.find_inner_item(&def)?; |
657 | (StructLoc { container, id }.intern(self.db).into(), def.name()) | 653 | (StructLoc { container, id }.intern(self.db).into(), def.name()) |
658 | } | 654 | } |
659 | ast::ModuleItem::EnumDef(def) => { | 655 | ast::Item::Enum(def) => { |
660 | let id = self.find_inner_item(&def)?; | 656 | let id = self.find_inner_item(&def)?; |
661 | (EnumLoc { container, id }.intern(self.db).into(), def.name()) | 657 | (EnumLoc { container, id }.intern(self.db).into(), def.name()) |
662 | } | 658 | } |
663 | ast::ModuleItem::UnionDef(def) => { | 659 | ast::Item::Union(def) => { |
664 | let id = self.find_inner_item(&def)?; | 660 | let id = self.find_inner_item(&def)?; |
665 | (UnionLoc { container, id }.intern(self.db).into(), def.name()) | 661 | (UnionLoc { container, id }.intern(self.db).into(), def.name()) |
666 | } | 662 | } |
667 | ast::ModuleItem::TraitDef(def) => { | 663 | ast::Item::Trait(def) => { |
668 | let id = self.find_inner_item(&def)?; | 664 | let id = self.find_inner_item(&def)?; |
669 | (TraitLoc { container, id }.intern(self.db).into(), def.name()) | 665 | (TraitLoc { container, id }.intern(self.db).into(), def.name()) |
670 | } | 666 | } |
671 | ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks | 667 | ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks |
672 | ast::ModuleItem::ImplDef(_) | 668 | ast::Item::Impl(_) |
673 | | ast::ModuleItem::UseItem(_) | 669 | | ast::Item::Use(_) |
674 | | ast::ModuleItem::ExternCrateItem(_) | 670 | | ast::Item::ExternCrate(_) |
675 | | ast::ModuleItem::Module(_) | 671 | | ast::Item::Module(_) |
676 | | ast::ModuleItem::MacroCall(_) => return None, | 672 | | ast::Item::MacroCall(_) => return None, |
677 | }; | 673 | }; |
678 | 674 | ||
679 | Some((def, name)) | 675 | Some((def, name)) |
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index a885ec96d..dcb00a1d9 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs | |||
@@ -162,7 +162,7 @@ impl ChildBySource for EnumId { | |||
162 | let arena_map = arena_map.as_ref(); | 162 | let arena_map = arena_map.as_ref(); |
163 | for (local_id, source) in arena_map.value.iter() { | 163 | for (local_id, source) in arena_map.value.iter() { |
164 | let id = EnumVariantId { parent: *self, local_id }; | 164 | let id = EnumVariantId { parent: *self, local_id }; |
165 | res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id) | 165 | res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id) |
166 | } | 166 | } |
167 | 167 | ||
168 | res | 168 | res |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 282ade2a3..88a8ef9bf 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -27,11 +27,12 @@ pub struct FunctionData { | |||
27 | /// can be called as a method. | 27 | /// can be called as a method. |
28 | pub has_self_param: bool, | 28 | pub has_self_param: bool, |
29 | pub is_unsafe: bool, | 29 | pub is_unsafe: bool, |
30 | pub is_varargs: bool, | ||
30 | pub visibility: RawVisibility, | 31 | pub visibility: RawVisibility, |
31 | } | 32 | } |
32 | 33 | ||
33 | impl FunctionData { | 34 | impl FunctionData { |
34 | pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { | 35 | pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { |
35 | let loc = func.lookup(db); | 36 | let loc = func.lookup(db); |
36 | let item_tree = db.item_tree(loc.id.file_id); | 37 | let item_tree = db.item_tree(loc.id.file_id); |
37 | let func = &item_tree[loc.id.value]; | 38 | let func = &item_tree[loc.id.value]; |
@@ -43,6 +44,7 @@ impl FunctionData { | |||
43 | attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), | 44 | attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), |
44 | has_self_param: func.has_self_param, | 45 | has_self_param: func.has_self_param, |
45 | is_unsafe: func.is_unsafe, | 46 | is_unsafe: func.is_unsafe, |
47 | is_varargs: func.is_varargs, | ||
46 | visibility: item_tree[func.visibility].clone(), | 48 | visibility: item_tree[func.visibility].clone(), |
47 | }) | 49 | }) |
48 | } | 50 | } |
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 6a0f493a7..8ea61fcf2 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -12,7 +12,7 @@ use hir_expand::{ | |||
12 | use ra_arena::{map::ArenaMap, Arena}; | 12 | use ra_arena::{map::ArenaMap, Arena}; |
13 | use ra_db::FileId; | 13 | use ra_db::FileId; |
14 | use ra_prof::profile; | 14 | use ra_prof::profile; |
15 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | 15 | use ra_syntax::ast::{self, GenericParamsOwner, NameOwner, TypeBoundsOwner}; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | body::LowerCtx, | 18 | body::LowerCtx, |
@@ -66,7 +66,7 @@ pub enum WherePredicateTarget { | |||
66 | TypeParam(LocalTypeParamId), | 66 | TypeParam(LocalTypeParamId), |
67 | } | 67 | } |
68 | 68 | ||
69 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; | 69 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; |
70 | 70 | ||
71 | impl GenericParams { | 71 | impl GenericParams { |
72 | pub(crate) fn generic_params_query( | 72 | pub(crate) fn generic_params_query( |
@@ -205,9 +205,9 @@ impl GenericParams { | |||
205 | &mut self, | 205 | &mut self, |
206 | lower_ctx: &LowerCtx, | 206 | lower_ctx: &LowerCtx, |
207 | sm: &mut SourceMap, | 207 | sm: &mut SourceMap, |
208 | node: &dyn TypeParamsOwner, | 208 | node: &dyn GenericParamsOwner, |
209 | ) { | 209 | ) { |
210 | if let Some(params) = node.type_param_list() { | 210 | if let Some(params) = node.generic_param_list() { |
211 | self.fill_params(lower_ctx, sm, params) | 211 | self.fill_params(lower_ctx, sm, params) |
212 | } | 212 | } |
213 | if let Some(where_clause) = node.where_clause() { | 213 | if let Some(where_clause) = node.where_clause() { |
@@ -232,7 +232,7 @@ impl GenericParams { | |||
232 | &mut self, | 232 | &mut self, |
233 | lower_ctx: &LowerCtx, | 233 | lower_ctx: &LowerCtx, |
234 | sm: &mut SourceMap, | 234 | sm: &mut SourceMap, |
235 | params: ast::TypeParamList, | 235 | params: ast::GenericParamList, |
236 | ) { | 236 | ) { |
237 | for type_param in params.type_params() { | 237 | for type_param in params.type_params() { |
238 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 238 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
@@ -317,7 +317,7 @@ impl GenericParams { | |||
317 | 317 | ||
318 | impl HasChildSource for GenericDefId { | 318 | impl HasChildSource for GenericDefId { |
319 | type ChildId = LocalTypeParamId; | 319 | type ChildId = LocalTypeParamId; |
320 | type Value = Either<ast::TraitDef, ast::TypeParam>; | 320 | type Value = Either<ast::Trait, ast::TypeParam>; |
321 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> { | 321 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> { |
322 | let (_, sm) = GenericParams::new(db, *self); | 322 | let (_, sm) = GenericParams::new(db, *self); |
323 | sm | 323 | sm |
diff --git a/crates/ra_hir_def/src/import_map.rs b/crates/ra_hir_def/src/import_map.rs index 68e20d06b..9e4c30b1a 100644 --- a/crates/ra_hir_def/src/import_map.rs +++ b/crates/ra_hir_def/src/import_map.rs | |||
@@ -5,14 +5,16 @@ use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc}; | |||
5 | use fst::{self, Streamer}; | 5 | use fst::{self, Streamer}; |
6 | use indexmap::{map::Entry, IndexMap}; | 6 | use indexmap::{map::Entry, IndexMap}; |
7 | use ra_db::CrateId; | 7 | use ra_db::CrateId; |
8 | use rustc_hash::FxHasher; | 8 | use ra_syntax::SmolStr; |
9 | use rustc_hash::{FxHashMap, FxHasher}; | ||
10 | use smallvec::SmallVec; | ||
9 | 11 | ||
10 | use crate::{ | 12 | use crate::{ |
11 | db::DefDatabase, | 13 | db::DefDatabase, |
12 | item_scope::ItemInNs, | 14 | item_scope::ItemInNs, |
13 | path::{ModPath, PathKind}, | 15 | path::{ModPath, PathKind}, |
14 | visibility::Visibility, | 16 | visibility::Visibility, |
15 | ModuleDefId, ModuleId, | 17 | AssocItemId, ModuleDefId, ModuleId, TraitId, |
16 | }; | 18 | }; |
17 | 19 | ||
18 | type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; | 20 | type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; |
@@ -34,6 +36,7 @@ pub struct ImportInfo { | |||
34 | /// | 36 | /// |
35 | /// Note that all paths are relative to the containing crate's root, so the crate name still needs | 37 | /// Note that all paths are relative to the containing crate's root, so the crate name still needs |
36 | /// to be prepended to the `ModPath` before the path is valid. | 38 | /// to be prepended to the `ModPath` before the path is valid. |
39 | #[derive(Default)] | ||
37 | pub struct ImportMap { | 40 | pub struct ImportMap { |
38 | map: FxIndexMap<ItemInNs, ImportInfo>, | 41 | map: FxIndexMap<ItemInNs, ImportInfo>, |
39 | 42 | ||
@@ -45,13 +48,17 @@ pub struct ImportMap { | |||
45 | /// the index of the first one. | 48 | /// the index of the first one. |
46 | importables: Vec<ItemInNs>, | 49 | importables: Vec<ItemInNs>, |
47 | fst: fst::Map<Vec<u8>>, | 50 | fst: fst::Map<Vec<u8>>, |
51 | |||
52 | /// Maps names of associated items to the item's ID. Only includes items whose defining trait is | ||
53 | /// exported. | ||
54 | assoc_map: FxHashMap<SmolStr, SmallVec<[AssocItemId; 1]>>, | ||
48 | } | 55 | } |
49 | 56 | ||
50 | impl ImportMap { | 57 | impl ImportMap { |
51 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { | 58 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { |
52 | let _p = ra_prof::profile("import_map_query"); | 59 | let _p = ra_prof::profile("import_map_query"); |
53 | let def_map = db.crate_def_map(krate); | 60 | let def_map = db.crate_def_map(krate); |
54 | let mut import_map = FxIndexMap::with_capacity_and_hasher(64, Default::default()); | 61 | let mut import_map = Self::default(); |
55 | 62 | ||
56 | // We look only into modules that are public(ly reexported), starting with the crate root. | 63 | // We look only into modules that are public(ly reexported), starting with the crate root. |
57 | let empty = ModPath { kind: PathKind::Plain, segments: vec![] }; | 64 | let empty = ModPath { kind: PathKind::Plain, segments: vec![] }; |
@@ -85,7 +92,7 @@ impl ImportMap { | |||
85 | 92 | ||
86 | for item in per_ns.iter_items() { | 93 | for item in per_ns.iter_items() { |
87 | let path = mk_path(); | 94 | let path = mk_path(); |
88 | match import_map.entry(item) { | 95 | match import_map.map.entry(item) { |
89 | Entry::Vacant(entry) => { | 96 | Entry::Vacant(entry) => { |
90 | entry.insert(ImportInfo { path, container: module }); | 97 | entry.insert(ImportInfo { path, container: module }); |
91 | } | 98 | } |
@@ -105,11 +112,16 @@ impl ImportMap { | |||
105 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | 112 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { |
106 | worklist.push((mod_id, mk_path())); | 113 | worklist.push((mod_id, mk_path())); |
107 | } | 114 | } |
115 | |||
116 | // If we've added a path to a trait, add the trait's methods to the method map. | ||
117 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
118 | import_map.collect_trait_methods(db, tr); | ||
119 | } | ||
108 | } | 120 | } |
109 | } | 121 | } |
110 | } | 122 | } |
111 | 123 | ||
112 | let mut importables = import_map.iter().collect::<Vec<_>>(); | 124 | let mut importables = import_map.map.iter().collect::<Vec<_>>(); |
113 | 125 | ||
114 | importables.sort_by(cmp); | 126 | importables.sort_by(cmp); |
115 | 127 | ||
@@ -133,10 +145,10 @@ impl ImportMap { | |||
133 | builder.insert(key, start as u64).unwrap(); | 145 | builder.insert(key, start as u64).unwrap(); |
134 | } | 146 | } |
135 | 147 | ||
136 | let fst = fst::Map::new(builder.into_inner().unwrap()).unwrap(); | 148 | import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap(); |
137 | let importables = importables.iter().map(|(item, _)| **item).collect(); | 149 | import_map.importables = importables.iter().map(|(item, _)| **item).collect(); |
138 | 150 | ||
139 | Arc::new(Self { map: import_map, fst, importables }) | 151 | Arc::new(import_map) |
140 | } | 152 | } |
141 | 153 | ||
142 | /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. | 154 | /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. |
@@ -147,6 +159,13 @@ impl ImportMap { | |||
147 | pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> { | 159 | pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> { |
148 | self.map.get(&item) | 160 | self.map.get(&item) |
149 | } | 161 | } |
162 | |||
163 | fn collect_trait_methods(&mut self, db: &dyn DefDatabase, tr: TraitId) { | ||
164 | let data = db.trait_data(tr); | ||
165 | for (name, item) in data.items.iter() { | ||
166 | self.assoc_map.entry(name.to_string().into()).or_default().push(*item); | ||
167 | } | ||
168 | } | ||
150 | } | 169 | } |
151 | 170 | ||
152 | impl PartialEq for ImportMap { | 171 | impl PartialEq for ImportMap { |
@@ -290,37 +309,32 @@ pub fn search_dependencies<'a>( | |||
290 | } | 309 | } |
291 | } | 310 | } |
292 | 311 | ||
312 | // Add all exported associated items whose names match the query (exactly). | ||
313 | for map in &import_maps { | ||
314 | if let Some(v) = map.assoc_map.get(&*query.query) { | ||
315 | res.extend(v.iter().map(|&assoc| { | ||
316 | ItemInNs::Types(match assoc { | ||
317 | AssocItemId::FunctionId(it) => it.into(), | ||
318 | AssocItemId::ConstId(it) => it.into(), | ||
319 | AssocItemId::TypeAliasId(it) => it.into(), | ||
320 | }) | ||
321 | })); | ||
322 | } | ||
323 | } | ||
324 | |||
293 | res | 325 | res |
294 | } | 326 | } |
295 | 327 | ||
296 | #[cfg(test)] | 328 | #[cfg(test)] |
297 | mod tests { | 329 | mod tests { |
298 | use super::*; | 330 | use expect::{expect, Expect}; |
299 | use crate::test_db::TestDB; | 331 | use ra_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
300 | use insta::assert_snapshot; | ||
301 | use itertools::Itertools; | ||
302 | use ra_db::fixture::WithFixture; | ||
303 | use ra_db::{SourceDatabase, Upcast}; | ||
304 | 332 | ||
305 | fn import_map(ra_fixture: &str) -> String { | 333 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; |
306 | let db = TestDB::with_files(ra_fixture); | ||
307 | let crate_graph = db.crate_graph(); | ||
308 | 334 | ||
309 | let s = crate_graph | 335 | use super::*; |
310 | .iter() | ||
311 | .filter_map(|krate| { | ||
312 | let cdata = &crate_graph[krate]; | ||
313 | let name = cdata.display_name.as_ref()?; | ||
314 | |||
315 | let map = db.import_map(krate); | ||
316 | |||
317 | Some(format!("{}:\n{:?}", name, map)) | ||
318 | }) | ||
319 | .join("\n"); | ||
320 | s | ||
321 | } | ||
322 | 336 | ||
323 | fn search_dependencies_of(ra_fixture: &str, krate_name: &str, query: Query) -> String { | 337 | fn check_search(ra_fixture: &str, krate_name: &str, query: Query, expect: Expect) { |
324 | let db = TestDB::with_files(ra_fixture); | 338 | let db = TestDB::with_files(ra_fixture); |
325 | let crate_graph = db.crate_graph(); | 339 | let crate_graph = db.crate_graph(); |
326 | let krate = crate_graph | 340 | let krate = crate_graph |
@@ -331,7 +345,7 @@ mod tests { | |||
331 | }) | 345 | }) |
332 | .unwrap(); | 346 | .unwrap(); |
333 | 347 | ||
334 | search_dependencies(db.upcast(), krate, query) | 348 | let actual = search_dependencies(db.upcast(), krate, query) |
335 | .into_iter() | 349 | .into_iter() |
336 | .filter_map(|item| { | 350 | .filter_map(|item| { |
337 | let mark = match item { | 351 | let mark = match item { |
@@ -339,23 +353,67 @@ mod tests { | |||
339 | ItemInNs::Values(_) => "v", | 353 | ItemInNs::Values(_) => "v", |
340 | ItemInNs::Macros(_) => "m", | 354 | ItemInNs::Macros(_) => "m", |
341 | }; | 355 | }; |
356 | let item = assoc_to_trait(&db, item); | ||
342 | item.krate(db.upcast()).map(|krate| { | 357 | item.krate(db.upcast()).map(|krate| { |
343 | let map = db.import_map(krate); | 358 | let map = db.import_map(krate); |
344 | let path = map.path_of(item).unwrap(); | 359 | let path = map.path_of(item).unwrap(); |
345 | format!( | 360 | format!( |
346 | "{}::{} ({})", | 361 | "{}::{} ({})\n", |
347 | crate_graph[krate].display_name.as_ref().unwrap(), | 362 | crate_graph[krate].display_name.as_ref().unwrap(), |
348 | path, | 363 | path, |
349 | mark | 364 | mark |
350 | ) | 365 | ) |
351 | }) | 366 | }) |
352 | }) | 367 | }) |
353 | .join("\n") | 368 | .collect::<String>(); |
369 | expect.assert_eq(&actual) | ||
370 | } | ||
371 | |||
372 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> ItemInNs { | ||
373 | let assoc: AssocItemId = match item { | ||
374 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { | ||
375 | ModuleDefId::TypeAliasId(it) => it.into(), | ||
376 | ModuleDefId::FunctionId(it) => it.into(), | ||
377 | ModuleDefId::ConstId(it) => it.into(), | ||
378 | _ => return item, | ||
379 | }, | ||
380 | _ => return item, | ||
381 | }; | ||
382 | |||
383 | let container = match assoc { | ||
384 | AssocItemId::FunctionId(it) => it.lookup(db).container, | ||
385 | AssocItemId::ConstId(it) => it.lookup(db).container, | ||
386 | AssocItemId::TypeAliasId(it) => it.lookup(db).container, | ||
387 | }; | ||
388 | |||
389 | match container { | ||
390 | AssocContainerId::TraitId(it) => ItemInNs::Types(it.into()), | ||
391 | _ => item, | ||
392 | } | ||
393 | } | ||
394 | |||
395 | fn check(ra_fixture: &str, expect: Expect) { | ||
396 | let db = TestDB::with_files(ra_fixture); | ||
397 | let crate_graph = db.crate_graph(); | ||
398 | |||
399 | let actual = crate_graph | ||
400 | .iter() | ||
401 | .filter_map(|krate| { | ||
402 | let cdata = &crate_graph[krate]; | ||
403 | let name = cdata.display_name.as_ref()?; | ||
404 | |||
405 | let map = db.import_map(krate); | ||
406 | |||
407 | Some(format!("{}:\n{:?}\n", name, map)) | ||
408 | }) | ||
409 | .collect::<String>(); | ||
410 | |||
411 | expect.assert_eq(&actual) | ||
354 | } | 412 | } |
355 | 413 | ||
356 | #[test] | 414 | #[test] |
357 | fn smoke() { | 415 | fn smoke() { |
358 | let map = import_map( | 416 | check( |
359 | r" | 417 | r" |
360 | //- /main.rs crate:main deps:lib | 418 | //- /main.rs crate:main deps:lib |
361 | 419 | ||
@@ -380,24 +438,23 @@ mod tests { | |||
380 | pub struct Pub2; // t + v | 438 | pub struct Pub2; // t + v |
381 | struct Priv; | 439 | struct Priv; |
382 | ", | 440 | ", |
441 | expect![[r#" | ||
442 | main: | ||
443 | - publ1 (t) | ||
444 | - real_pu2 (t) | ||
445 | - real_pub (t) | ||
446 | - real_pub::Pub (t) | ||
447 | lib: | ||
448 | - Pub (t) | ||
449 | - Pub2 (t) | ||
450 | - Pub2 (v) | ||
451 | "#]], | ||
383 | ); | 452 | ); |
384 | |||
385 | assert_snapshot!(map, @r###" | ||
386 | main: | ||
387 | - publ1 (t) | ||
388 | - real_pu2 (t) | ||
389 | - real_pub (t) | ||
390 | - real_pub::Pub (t) | ||
391 | lib: | ||
392 | - Pub (t) | ||
393 | - Pub2 (t) | ||
394 | - Pub2 (v) | ||
395 | "###); | ||
396 | } | 453 | } |
397 | 454 | ||
398 | #[test] | 455 | #[test] |
399 | fn prefers_shortest_path() { | 456 | fn prefers_shortest_path() { |
400 | let map = import_map( | 457 | check( |
401 | r" | 458 | r" |
402 | //- /main.rs crate:main | 459 | //- /main.rs crate:main |
403 | 460 | ||
@@ -409,21 +466,20 @@ mod tests { | |||
409 | pub use super::sub::subsub::Def; | 466 | pub use super::sub::subsub::Def; |
410 | } | 467 | } |
411 | ", | 468 | ", |
469 | expect![[r#" | ||
470 | main: | ||
471 | - sub (t) | ||
472 | - sub::Def (t) | ||
473 | - sub::subsub (t) | ||
474 | "#]], | ||
412 | ); | 475 | ); |
413 | |||
414 | assert_snapshot!(map, @r###" | ||
415 | main: | ||
416 | - sub (t) | ||
417 | - sub::Def (t) | ||
418 | - sub::subsub (t) | ||
419 | "###); | ||
420 | } | 476 | } |
421 | 477 | ||
422 | #[test] | 478 | #[test] |
423 | fn type_reexport_cross_crate() { | 479 | fn type_reexport_cross_crate() { |
424 | // Reexports need to be visible from a crate, even if the original crate exports the item | 480 | // Reexports need to be visible from a crate, even if the original crate exports the item |
425 | // at a shorter path. | 481 | // at a shorter path. |
426 | let map = import_map( | 482 | check( |
427 | r" | 483 | r" |
428 | //- /main.rs crate:main deps:lib | 484 | //- /main.rs crate:main deps:lib |
429 | pub mod m { | 485 | pub mod m { |
@@ -432,22 +488,21 @@ mod tests { | |||
432 | //- /lib.rs crate:lib | 488 | //- /lib.rs crate:lib |
433 | pub struct S; | 489 | pub struct S; |
434 | ", | 490 | ", |
491 | expect![[r#" | ||
492 | main: | ||
493 | - m (t) | ||
494 | - m::S (t) | ||
495 | - m::S (v) | ||
496 | lib: | ||
497 | - S (t) | ||
498 | - S (v) | ||
499 | "#]], | ||
435 | ); | 500 | ); |
436 | |||
437 | assert_snapshot!(map, @r###" | ||
438 | main: | ||
439 | - m (t) | ||
440 | - m::S (t) | ||
441 | - m::S (v) | ||
442 | lib: | ||
443 | - S (t) | ||
444 | - S (v) | ||
445 | "###); | ||
446 | } | 501 | } |
447 | 502 | ||
448 | #[test] | 503 | #[test] |
449 | fn macro_reexport() { | 504 | fn macro_reexport() { |
450 | let map = import_map( | 505 | check( |
451 | r" | 506 | r" |
452 | //- /main.rs crate:main deps:lib | 507 | //- /main.rs crate:main deps:lib |
453 | pub mod m { | 508 | pub mod m { |
@@ -459,21 +514,20 @@ mod tests { | |||
459 | () => {}; | 514 | () => {}; |
460 | } | 515 | } |
461 | ", | 516 | ", |
517 | expect![[r#" | ||
518 | main: | ||
519 | - m (t) | ||
520 | - m::pub_macro (m) | ||
521 | lib: | ||
522 | - pub_macro (m) | ||
523 | "#]], | ||
462 | ); | 524 | ); |
463 | |||
464 | assert_snapshot!(map, @r###" | ||
465 | main: | ||
466 | - m (t) | ||
467 | - m::pub_macro (m) | ||
468 | lib: | ||
469 | - pub_macro (m) | ||
470 | "###); | ||
471 | } | 525 | } |
472 | 526 | ||
473 | #[test] | 527 | #[test] |
474 | fn module_reexport() { | 528 | fn module_reexport() { |
475 | // Reexporting modules from a dependency adds all contents to the import map. | 529 | // Reexporting modules from a dependency adds all contents to the import map. |
476 | let map = import_map( | 530 | check( |
477 | r" | 531 | r" |
478 | //- /main.rs crate:main deps:lib | 532 | //- /main.rs crate:main deps:lib |
479 | pub use lib::module as reexported_module; | 533 | pub use lib::module as reexported_module; |
@@ -482,24 +536,23 @@ mod tests { | |||
482 | pub struct S; | 536 | pub struct S; |
483 | } | 537 | } |
484 | ", | 538 | ", |
539 | expect![[r#" | ||
540 | main: | ||
541 | - reexported_module (t) | ||
542 | - reexported_module::S (t) | ||
543 | - reexported_module::S (v) | ||
544 | lib: | ||
545 | - module (t) | ||
546 | - module::S (t) | ||
547 | - module::S (v) | ||
548 | "#]], | ||
485 | ); | 549 | ); |
486 | |||
487 | assert_snapshot!(map, @r###" | ||
488 | main: | ||
489 | - reexported_module (t) | ||
490 | - reexported_module::S (t) | ||
491 | - reexported_module::S (v) | ||
492 | lib: | ||
493 | - module (t) | ||
494 | - module::S (t) | ||
495 | - module::S (v) | ||
496 | "###); | ||
497 | } | 550 | } |
498 | 551 | ||
499 | #[test] | 552 | #[test] |
500 | fn cyclic_module_reexport() { | 553 | fn cyclic_module_reexport() { |
501 | // A cyclic reexport does not hang. | 554 | // A cyclic reexport does not hang. |
502 | let map = import_map( | 555 | check( |
503 | r" | 556 | r" |
504 | //- /lib.rs crate:lib | 557 | //- /lib.rs crate:lib |
505 | pub mod module { | 558 | pub mod module { |
@@ -511,36 +564,35 @@ mod tests { | |||
511 | pub use super::module; | 564 | pub use super::module; |
512 | } | 565 | } |
513 | ", | 566 | ", |
567 | expect![[r#" | ||
568 | lib: | ||
569 | - module (t) | ||
570 | - module::S (t) | ||
571 | - module::S (v) | ||
572 | - sub (t) | ||
573 | "#]], | ||
514 | ); | 574 | ); |
515 | |||
516 | assert_snapshot!(map, @r###" | ||
517 | lib: | ||
518 | - module (t) | ||
519 | - module::S (t) | ||
520 | - module::S (v) | ||
521 | - sub (t) | ||
522 | "###); | ||
523 | } | 575 | } |
524 | 576 | ||
525 | #[test] | 577 | #[test] |
526 | fn private_macro() { | 578 | fn private_macro() { |
527 | let map = import_map( | 579 | check( |
528 | r" | 580 | r" |
529 | //- /lib.rs crate:lib | 581 | //- /lib.rs crate:lib |
530 | macro_rules! private_macro { | 582 | macro_rules! private_macro { |
531 | () => {}; | 583 | () => {}; |
532 | } | 584 | } |
533 | ", | 585 | ", |
534 | ); | 586 | expect![[r#" |
587 | lib: | ||
535 | 588 | ||
536 | assert_snapshot!(map, @r###" | 589 | "#]], |
537 | lib: | 590 | ); |
538 | "###); | ||
539 | } | 591 | } |
540 | 592 | ||
541 | #[test] | 593 | #[test] |
542 | fn namespacing() { | 594 | fn namespacing() { |
543 | let map = import_map( | 595 | check( |
544 | r" | 596 | r" |
545 | //- /lib.rs crate:lib | 597 | //- /lib.rs crate:lib |
546 | pub struct Thing; // t + v | 598 | pub struct Thing; // t + v |
@@ -549,16 +601,15 @@ mod tests { | |||
549 | () => {}; | 601 | () => {}; |
550 | } | 602 | } |
551 | ", | 603 | ", |
604 | expect![[r#" | ||
605 | lib: | ||
606 | - Thing (m) | ||
607 | - Thing (t) | ||
608 | - Thing (v) | ||
609 | "#]], | ||
552 | ); | 610 | ); |
553 | 611 | ||
554 | assert_snapshot!(map, @r###" | 612 | check( |
555 | lib: | ||
556 | - Thing (m) | ||
557 | - Thing (t) | ||
558 | - Thing (v) | ||
559 | "###); | ||
560 | |||
561 | let map = import_map( | ||
562 | r" | 613 | r" |
563 | //- /lib.rs crate:lib | 614 | //- /lib.rs crate:lib |
564 | pub mod Thing {} // t | 615 | pub mod Thing {} // t |
@@ -567,13 +618,12 @@ mod tests { | |||
567 | () => {}; | 618 | () => {}; |
568 | } | 619 | } |
569 | ", | 620 | ", |
621 | expect![[r#" | ||
622 | lib: | ||
623 | - Thing (m) | ||
624 | - Thing (t) | ||
625 | "#]], | ||
570 | ); | 626 | ); |
571 | |||
572 | assert_snapshot!(map, @r###" | ||
573 | lib: | ||
574 | - Thing (m) | ||
575 | - Thing (t) | ||
576 | "###); | ||
577 | } | 627 | } |
578 | 628 | ||
579 | #[test] | 629 | #[test] |
@@ -602,23 +652,33 @@ mod tests { | |||
602 | } | 652 | } |
603 | "#; | 653 | "#; |
604 | 654 | ||
605 | let res = search_dependencies_of(ra_fixture, "main", Query::new("fmt")); | 655 | check_search( |
606 | assert_snapshot!(res, @r###" | 656 | ra_fixture, |
607 | dep::fmt (t) | 657 | "main", |
608 | dep::Fmt (t) | 658 | Query::new("fmt"), |
609 | dep::Fmt (v) | 659 | expect![[r#" |
610 | dep::Fmt (m) | 660 | dep::fmt (t) |
611 | dep::fmt::Display (t) | 661 | dep::Fmt (t) |
612 | dep::format (v) | 662 | dep::Fmt (v) |
613 | "###); | 663 | dep::Fmt (m) |
614 | 664 | dep::fmt::Display (t) | |
615 | let res = search_dependencies_of(ra_fixture, "main", Query::new("fmt").anchor_end()); | 665 | dep::format (v) |
616 | assert_snapshot!(res, @r###" | 666 | dep::fmt::Display (t) |
617 | dep::fmt (t) | 667 | "#]], |
618 | dep::Fmt (t) | 668 | ); |
619 | dep::Fmt (v) | 669 | |
620 | dep::Fmt (m) | 670 | check_search( |
621 | "###); | 671 | ra_fixture, |
672 | "main", | ||
673 | Query::new("fmt").anchor_end(), | ||
674 | expect![[r#" | ||
675 | dep::fmt (t) | ||
676 | dep::Fmt (t) | ||
677 | dep::Fmt (v) | ||
678 | dep::Fmt (m) | ||
679 | dep::fmt::Display (t) | ||
680 | "#]], | ||
681 | ); | ||
622 | } | 682 | } |
623 | 683 | ||
624 | #[test] | 684 | #[test] |
@@ -631,26 +691,32 @@ mod tests { | |||
631 | pub struct FMT; | 691 | pub struct FMT; |
632 | "#; | 692 | "#; |
633 | 693 | ||
634 | let res = search_dependencies_of(ra_fixture, "main", Query::new("FMT")); | 694 | check_search( |
635 | 695 | ra_fixture, | |
636 | assert_snapshot!(res, @r###" | 696 | "main", |
637 | dep::fmt (t) | 697 | Query::new("FMT"), |
638 | dep::fmt (v) | 698 | expect![[r#" |
639 | dep::FMT (t) | 699 | dep::fmt (t) |
640 | dep::FMT (v) | 700 | dep::fmt (v) |
641 | "###); | 701 | dep::FMT (t) |
642 | 702 | dep::FMT (v) | |
643 | let res = search_dependencies_of(ra_fixture, "main", Query::new("FMT").case_sensitive()); | 703 | "#]], |
704 | ); | ||
644 | 705 | ||
645 | assert_snapshot!(res, @r###" | 706 | check_search( |
646 | dep::FMT (t) | 707 | ra_fixture, |
647 | dep::FMT (v) | 708 | "main", |
648 | "###); | 709 | Query::new("FMT").case_sensitive(), |
710 | expect![[r#" | ||
711 | dep::FMT (t) | ||
712 | dep::FMT (v) | ||
713 | "#]], | ||
714 | ); | ||
649 | } | 715 | } |
650 | 716 | ||
651 | #[test] | 717 | #[test] |
652 | fn search_limit() { | 718 | fn search_limit() { |
653 | let res = search_dependencies_of( | 719 | check_search( |
654 | r#" | 720 | r#" |
655 | //- /main.rs crate:main deps:dep | 721 | //- /main.rs crate:main deps:dep |
656 | //- /dep.rs crate:dep | 722 | //- /dep.rs crate:dep |
@@ -670,10 +736,10 @@ mod tests { | |||
670 | "#, | 736 | "#, |
671 | "main", | 737 | "main", |
672 | Query::new("").limit(2), | 738 | Query::new("").limit(2), |
739 | expect![[r#" | ||
740 | dep::fmt (t) | ||
741 | dep::Fmt (t) | ||
742 | "#]], | ||
673 | ); | 743 | ); |
674 | assert_snapshot!(res, @r###" | ||
675 | dep::fmt (t) | ||
676 | dep::Fmt (t) | ||
677 | "###); | ||
678 | } | 744 | } |
679 | } | 745 | } |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 4d446c707..8fee4b15e 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | //! Describes items defined or visible (ie, imported) in a certain scope. | 1 | //! Describes items defined or visible (ie, imported) in a certain scope. |
2 | //! This is shared between modules and blocks. | 2 | //! This is shared between modules and blocks. |
3 | 3 | ||
4 | use std::collections::hash_map::Entry; | ||
5 | |||
4 | use hir_expand::name::Name; | 6 | use hir_expand::name::Name; |
5 | use once_cell::sync::Lazy; | 7 | use once_cell::sync::Lazy; |
6 | use ra_db::CrateId; | 8 | use ra_db::CrateId; |
@@ -27,9 +29,15 @@ pub struct PerNsGlobImports { | |||
27 | 29 | ||
28 | #[derive(Debug, Default, PartialEq, Eq)] | 30 | #[derive(Debug, Default, PartialEq, Eq)] |
29 | pub struct ItemScope { | 31 | pub struct ItemScope { |
30 | visible: FxHashMap<Name, PerNs>, | 32 | types: FxHashMap<Name, (ModuleDefId, Visibility)>, |
33 | values: FxHashMap<Name, (ModuleDefId, Visibility)>, | ||
34 | macros: FxHashMap<Name, (MacroDefId, Visibility)>, | ||
35 | unresolved: FxHashSet<Name>, | ||
36 | |||
31 | defs: Vec<ModuleDefId>, | 37 | defs: Vec<ModuleDefId>, |
32 | impls: Vec<ImplId>, | 38 | impls: Vec<ImplId>, |
39 | /// Traits imported via `use Trait as _;`. | ||
40 | unnamed_trait_imports: FxHashMap<TraitId, Visibility>, | ||
33 | /// Macros visible in current module in legacy textual scope | 41 | /// Macros visible in current module in legacy textual scope |
34 | /// | 42 | /// |
35 | /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. | 43 | /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. |
@@ -65,14 +73,16 @@ pub(crate) enum BuiltinShadowMode { | |||
65 | /// Other methods will only resolve values, types and module scoped macros only. | 73 | /// Other methods will only resolve values, types and module scoped macros only. |
66 | impl ItemScope { | 74 | impl ItemScope { |
67 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { | 75 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { |
68 | //FIXME: shadowing | 76 | // FIXME: shadowing |
69 | self.visible.iter().map(|(n, def)| (n, *def)) | 77 | let keys: FxHashSet<_> = self |
70 | } | 78 | .types |
71 | 79 | .keys() | |
72 | pub fn entries_without_primitives<'a>( | 80 | .chain(self.values.keys()) |
73 | &'a self, | 81 | .chain(self.macros.keys()) |
74 | ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { | 82 | .chain(self.unresolved.iter()) |
75 | self.visible.iter().map(|(n, def)| (n, *def)) | 83 | .collect(); |
84 | |||
85 | keys.into_iter().map(move |name| (name, self.get(name))) | ||
76 | } | 86 | } |
77 | 87 | ||
78 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { | 88 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { |
@@ -91,7 +101,7 @@ impl ItemScope { | |||
91 | 101 | ||
92 | /// Iterate over all module scoped macros | 102 | /// Iterate over all module scoped macros |
93 | pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | 103 | pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { |
94 | self.visible.iter().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) | 104 | self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) |
95 | } | 105 | } |
96 | 106 | ||
97 | /// Iterate over all legacy textual scoped macros visible at the end of the module | 107 | /// Iterate over all legacy textual scoped macros visible at the end of the module |
@@ -101,12 +111,16 @@ impl ItemScope { | |||
101 | 111 | ||
102 | /// Get a name from current module scope, legacy macros are not included | 112 | /// Get a name from current module scope, legacy macros are not included |
103 | pub(crate) fn get(&self, name: &Name) -> PerNs { | 113 | pub(crate) fn get(&self, name: &Name) -> PerNs { |
104 | self.visible.get(name).copied().unwrap_or_else(PerNs::none) | 114 | PerNs { |
115 | types: self.types.get(name).copied(), | ||
116 | values: self.values.get(name).copied(), | ||
117 | macros: self.macros.get(name).copied(), | ||
118 | } | ||
105 | } | 119 | } |
106 | 120 | ||
107 | pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { | 121 | pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { |
108 | for (name, per_ns) in &self.visible { | 122 | for (name, per_ns) in self.entries() { |
109 | if let Some(vis) = item.match_with(*per_ns) { | 123 | if let Some(vis) = item.match_with(per_ns) { |
110 | return Some((name, vis)); | 124 | return Some((name, vis)); |
111 | } | 125 | } |
112 | } | 126 | } |
@@ -114,10 +128,13 @@ impl ItemScope { | |||
114 | } | 128 | } |
115 | 129 | ||
116 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { | 130 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { |
117 | self.visible.values().filter_map(|def| match def.take_types() { | 131 | self.types |
118 | Some(ModuleDefId::TraitId(t)) => Some(t), | 132 | .values() |
119 | _ => None, | 133 | .filter_map(|(def, _)| match def { |
120 | }) | 134 | ModuleDefId::TraitId(t) => Some(*t), |
135 | _ => None, | ||
136 | }) | ||
137 | .chain(self.unnamed_trait_imports.keys().copied()) | ||
121 | } | 138 | } |
122 | 139 | ||
123 | pub(crate) fn define_def(&mut self, def: ModuleDefId) { | 140 | pub(crate) fn define_def(&mut self, def: ModuleDefId) { |
@@ -136,23 +153,40 @@ impl ItemScope { | |||
136 | self.legacy_macros.insert(name, mac); | 153 | self.legacy_macros.insert(name, mac); |
137 | } | 154 | } |
138 | 155 | ||
156 | pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> { | ||
157 | self.unnamed_trait_imports.get(&tr).copied() | ||
158 | } | ||
159 | |||
160 | pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { | ||
161 | self.unnamed_trait_imports.insert(tr, vis); | ||
162 | } | ||
163 | |||
139 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { | 164 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { |
140 | let mut changed = false; | 165 | let mut changed = false; |
141 | let existing = self.visible.entry(name).or_default(); | ||
142 | 166 | ||
143 | if existing.types.is_none() && def.types.is_some() { | 167 | if let Some(types) = def.types { |
144 | existing.types = def.types; | 168 | self.types.entry(name.clone()).or_insert_with(|| { |
145 | changed = true; | 169 | changed = true; |
170 | types | ||
171 | }); | ||
146 | } | 172 | } |
147 | 173 | if let Some(values) = def.values { | |
148 | if existing.values.is_none() && def.values.is_some() { | 174 | self.values.entry(name.clone()).or_insert_with(|| { |
149 | existing.values = def.values; | 175 | changed = true; |
150 | changed = true; | 176 | values |
177 | }); | ||
178 | } | ||
179 | if let Some(macros) = def.macros { | ||
180 | self.macros.entry(name.clone()).or_insert_with(|| { | ||
181 | changed = true; | ||
182 | macros | ||
183 | }); | ||
151 | } | 184 | } |
152 | 185 | ||
153 | if existing.macros.is_none() && def.macros.is_some() { | 186 | if def.is_none() { |
154 | existing.macros = def.macros; | 187 | if self.unresolved.insert(name) { |
155 | changed = true; | 188 | changed = true; |
189 | } | ||
156 | } | 190 | } |
157 | 191 | ||
158 | changed | 192 | changed |
@@ -166,17 +200,17 @@ impl ItemScope { | |||
166 | def_import_type: ImportType, | 200 | def_import_type: ImportType, |
167 | ) -> bool { | 201 | ) -> bool { |
168 | let mut changed = false; | 202 | let mut changed = false; |
169 | let existing = self.visible.entry(lookup.1.clone()).or_default(); | ||
170 | 203 | ||
171 | macro_rules! check_changed { | 204 | macro_rules! check_changed { |
172 | ( | 205 | ( |
173 | $changed:ident, | 206 | $changed:ident, |
174 | ( $existing:ident / $def:ident ) . $field:ident, | 207 | ( $this:ident / $def:ident ) . $field:ident, |
175 | $glob_imports:ident [ $lookup:ident ], | 208 | $glob_imports:ident [ $lookup:ident ], |
176 | $def_import_type:ident | 209 | $def_import_type:ident |
177 | ) => { | 210 | ) => {{ |
178 | match ($existing.$field, $def.$field) { | 211 | let existing = $this.$field.entry($lookup.1.clone()); |
179 | (None, Some(_)) => { | 212 | match (existing, $def.$field) { |
213 | (Entry::Vacant(entry), Some(_)) => { | ||
180 | match $def_import_type { | 214 | match $def_import_type { |
181 | ImportType::Glob => { | 215 | ImportType::Glob => { |
182 | $glob_imports.$field.insert($lookup.clone()); | 216 | $glob_imports.$field.insert($lookup.clone()); |
@@ -186,32 +220,46 @@ impl ItemScope { | |||
186 | } | 220 | } |
187 | } | 221 | } |
188 | 222 | ||
189 | $existing.$field = $def.$field; | 223 | if let Some(fld) = $def.$field { |
224 | entry.insert(fld); | ||
225 | } | ||
190 | $changed = true; | 226 | $changed = true; |
191 | } | 227 | } |
192 | (Some(_), Some(_)) | 228 | (Entry::Occupied(mut entry), Some(_)) |
193 | if $glob_imports.$field.contains(&$lookup) | 229 | if $glob_imports.$field.contains(&$lookup) |
194 | && matches!($def_import_type, ImportType::Named) => | 230 | && matches!($def_import_type, ImportType::Named) => |
195 | { | 231 | { |
196 | mark::hit!(import_shadowed); | 232 | mark::hit!(import_shadowed); |
197 | $glob_imports.$field.remove(&$lookup); | 233 | $glob_imports.$field.remove(&$lookup); |
198 | $existing.$field = $def.$field; | 234 | if let Some(fld) = $def.$field { |
235 | entry.insert(fld); | ||
236 | } | ||
199 | $changed = true; | 237 | $changed = true; |
200 | } | 238 | } |
201 | _ => {} | 239 | _ => {} |
202 | } | 240 | } |
203 | }; | 241 | }}; |
204 | } | 242 | } |
205 | 243 | ||
206 | check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type); | 244 | check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type); |
207 | check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type); | 245 | check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); |
208 | check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type); | 246 | check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); |
247 | |||
248 | if def.is_none() { | ||
249 | if self.unresolved.insert(lookup.1) { | ||
250 | changed = true; | ||
251 | } | ||
252 | } | ||
209 | 253 | ||
210 | changed | 254 | changed |
211 | } | 255 | } |
212 | 256 | ||
213 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { | 257 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Option<Name>, PerNs)> + 'a { |
214 | self.visible.iter().map(|(name, res)| (name.clone(), *res)) | 258 | self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( |
259 | self.unnamed_trait_imports | ||
260 | .iter() | ||
261 | .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), | ||
262 | ) | ||
215 | } | 263 | } |
216 | 264 | ||
217 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { | 265 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { |
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index 3e603bd55..a67e75dac 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -13,7 +13,7 @@ use std::{ | |||
13 | sync::Arc, | 13 | sync::Arc, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use ast::{AstNode, AttrsOwner, NameOwner, StructKind, TypeAscriptionOwner}; | 16 | use ast::{AstNode, AttrsOwner, NameOwner, StructKind}; |
17 | use either::Either; | 17 | use either::Either; |
18 | use hir_expand::{ | 18 | use hir_expand::{ |
19 | ast_id_map::FileAstId, | 19 | ast_id_map::FileAstId, |
@@ -70,7 +70,7 @@ impl GenericParamsId { | |||
70 | pub struct ItemTree { | 70 | pub struct ItemTree { |
71 | top_level: SmallVec<[ModItem; 1]>, | 71 | top_level: SmallVec<[ModItem; 1]>, |
72 | attrs: FxHashMap<AttrOwner, Attrs>, | 72 | attrs: FxHashMap<AttrOwner, Attrs>, |
73 | inner_items: FxHashMap<FileAstId<ast::ModuleItem>, SmallVec<[ModItem; 1]>>, | 73 | inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, |
74 | 74 | ||
75 | data: Option<Box<ItemTreeData>>, | 75 | data: Option<Box<ItemTreeData>>, |
76 | } | 76 | } |
@@ -187,7 +187,7 @@ impl ItemTree { | |||
187 | /// | 187 | /// |
188 | /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered | 188 | /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered |
189 | /// to multiple items in the `ItemTree`. | 189 | /// to multiple items in the `ItemTree`. |
190 | pub fn inner_items(&self, ast: FileAstId<ast::ModuleItem>) -> &[ModItem] { | 190 | pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] { |
191 | &self.inner_items[&ast] | 191 | &self.inner_items[&ast] |
192 | } | 192 | } |
193 | 193 | ||
@@ -310,7 +310,7 @@ from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); | |||
310 | 310 | ||
311 | /// Trait implemented by all item nodes in the item tree. | 311 | /// Trait implemented by all item nodes in the item tree. |
312 | pub trait ItemTreeNode: Clone { | 312 | pub trait ItemTreeNode: Clone { |
313 | type Source: AstNode + Into<ast::ModuleItem>; | 313 | type Source: AstNode + Into<ast::Item>; |
314 | 314 | ||
315 | fn ast_id(&self) -> FileAstId<Self::Source>; | 315 | fn ast_id(&self) -> FileAstId<Self::Source>; |
316 | 316 | ||
@@ -411,17 +411,17 @@ macro_rules! mod_items { | |||
411 | } | 411 | } |
412 | 412 | ||
413 | mod_items! { | 413 | mod_items! { |
414 | Import in imports -> ast::UseItem, | 414 | Import in imports -> ast::Use, |
415 | ExternCrate in extern_crates -> ast::ExternCrateItem, | 415 | ExternCrate in extern_crates -> ast::ExternCrate, |
416 | Function in functions -> ast::FnDef, | 416 | Function in functions -> ast::Fn, |
417 | Struct in structs -> ast::StructDef, | 417 | Struct in structs -> ast::Struct, |
418 | Union in unions -> ast::UnionDef, | 418 | Union in unions -> ast::Union, |
419 | Enum in enums -> ast::EnumDef, | 419 | Enum in enums -> ast::Enum, |
420 | Const in consts -> ast::ConstDef, | 420 | Const in consts -> ast::Const, |
421 | Static in statics -> ast::StaticDef, | 421 | Static in statics -> ast::Static, |
422 | Trait in traits -> ast::TraitDef, | 422 | Trait in traits -> ast::Trait, |
423 | Impl in impls -> ast::ImplDef, | 423 | Impl in impls -> ast::Impl, |
424 | TypeAlias in type_aliases -> ast::TypeAliasDef, | 424 | TypeAlias in type_aliases -> ast::TypeAlias, |
425 | Mod in mods -> ast::Module, | 425 | Mod in mods -> ast::Module, |
426 | MacroCall in macro_calls -> ast::MacroCall, | 426 | MacroCall in macro_calls -> ast::MacroCall, |
427 | } | 427 | } |
@@ -482,7 +482,7 @@ pub struct Import { | |||
482 | pub is_prelude: bool, | 482 | pub is_prelude: bool, |
483 | /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many | 483 | /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many |
484 | /// `Import`s can map to the same `use` item. | 484 | /// `Import`s can map to the same `use` item. |
485 | pub ast_id: FileAstId<ast::UseItem>, | 485 | pub ast_id: FileAstId<ast::Use>, |
486 | } | 486 | } |
487 | 487 | ||
488 | #[derive(Debug, Clone, Eq, PartialEq)] | 488 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -492,7 +492,7 @@ pub struct ExternCrate { | |||
492 | pub visibility: RawVisibilityId, | 492 | pub visibility: RawVisibilityId, |
493 | /// Whether this is a `#[macro_use] extern crate ...`. | 493 | /// Whether this is a `#[macro_use] extern crate ...`. |
494 | pub is_macro_use: bool, | 494 | pub is_macro_use: bool, |
495 | pub ast_id: FileAstId<ast::ExternCrateItem>, | 495 | pub ast_id: FileAstId<ast::ExternCrate>, |
496 | } | 496 | } |
497 | 497 | ||
498 | #[derive(Debug, Clone, Eq, PartialEq)] | 498 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -503,8 +503,9 @@ pub struct Function { | |||
503 | pub has_self_param: bool, | 503 | pub has_self_param: bool, |
504 | pub is_unsafe: bool, | 504 | pub is_unsafe: bool, |
505 | pub params: Box<[TypeRef]>, | 505 | pub params: Box<[TypeRef]>, |
506 | pub is_varargs: bool, | ||
506 | pub ret_type: TypeRef, | 507 | pub ret_type: TypeRef, |
507 | pub ast_id: FileAstId<ast::FnDef>, | 508 | pub ast_id: FileAstId<ast::Fn>, |
508 | } | 509 | } |
509 | 510 | ||
510 | #[derive(Debug, Clone, Eq, PartialEq)] | 511 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -513,7 +514,7 @@ pub struct Struct { | |||
513 | pub visibility: RawVisibilityId, | 514 | pub visibility: RawVisibilityId, |
514 | pub generic_params: GenericParamsId, | 515 | pub generic_params: GenericParamsId, |
515 | pub fields: Fields, | 516 | pub fields: Fields, |
516 | pub ast_id: FileAstId<ast::StructDef>, | 517 | pub ast_id: FileAstId<ast::Struct>, |
517 | pub kind: StructDefKind, | 518 | pub kind: StructDefKind, |
518 | } | 519 | } |
519 | 520 | ||
@@ -533,7 +534,7 @@ pub struct Union { | |||
533 | pub visibility: RawVisibilityId, | 534 | pub visibility: RawVisibilityId, |
534 | pub generic_params: GenericParamsId, | 535 | pub generic_params: GenericParamsId, |
535 | pub fields: Fields, | 536 | pub fields: Fields, |
536 | pub ast_id: FileAstId<ast::UnionDef>, | 537 | pub ast_id: FileAstId<ast::Union>, |
537 | } | 538 | } |
538 | 539 | ||
539 | #[derive(Debug, Clone, Eq, PartialEq)] | 540 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -542,7 +543,7 @@ pub struct Enum { | |||
542 | pub visibility: RawVisibilityId, | 543 | pub visibility: RawVisibilityId, |
543 | pub generic_params: GenericParamsId, | 544 | pub generic_params: GenericParamsId, |
544 | pub variants: IdRange<Variant>, | 545 | pub variants: IdRange<Variant>, |
545 | pub ast_id: FileAstId<ast::EnumDef>, | 546 | pub ast_id: FileAstId<ast::Enum>, |
546 | } | 547 | } |
547 | 548 | ||
548 | #[derive(Debug, Clone, Eq, PartialEq)] | 549 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -551,7 +552,7 @@ pub struct Const { | |||
551 | pub name: Option<Name>, | 552 | pub name: Option<Name>, |
552 | pub visibility: RawVisibilityId, | 553 | pub visibility: RawVisibilityId, |
553 | pub type_ref: TypeRef, | 554 | pub type_ref: TypeRef, |
554 | pub ast_id: FileAstId<ast::ConstDef>, | 555 | pub ast_id: FileAstId<ast::Const>, |
555 | } | 556 | } |
556 | 557 | ||
557 | #[derive(Debug, Clone, Eq, PartialEq)] | 558 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -560,7 +561,7 @@ pub struct Static { | |||
560 | pub visibility: RawVisibilityId, | 561 | pub visibility: RawVisibilityId, |
561 | pub mutable: bool, | 562 | pub mutable: bool, |
562 | pub type_ref: TypeRef, | 563 | pub type_ref: TypeRef, |
563 | pub ast_id: FileAstId<ast::StaticDef>, | 564 | pub ast_id: FileAstId<ast::Static>, |
564 | } | 565 | } |
565 | 566 | ||
566 | #[derive(Debug, Clone, Eq, PartialEq)] | 567 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -570,7 +571,7 @@ pub struct Trait { | |||
570 | pub generic_params: GenericParamsId, | 571 | pub generic_params: GenericParamsId, |
571 | pub auto: bool, | 572 | pub auto: bool, |
572 | pub items: Box<[AssocItem]>, | 573 | pub items: Box<[AssocItem]>, |
573 | pub ast_id: FileAstId<ast::TraitDef>, | 574 | pub ast_id: FileAstId<ast::Trait>, |
574 | } | 575 | } |
575 | 576 | ||
576 | #[derive(Debug, Clone, Eq, PartialEq)] | 577 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -580,7 +581,7 @@ pub struct Impl { | |||
580 | pub target_type: TypeRef, | 581 | pub target_type: TypeRef, |
581 | pub is_negative: bool, | 582 | pub is_negative: bool, |
582 | pub items: Box<[AssocItem]>, | 583 | pub items: Box<[AssocItem]>, |
583 | pub ast_id: FileAstId<ast::ImplDef>, | 584 | pub ast_id: FileAstId<ast::Impl>, |
584 | } | 585 | } |
585 | 586 | ||
586 | #[derive(Debug, Clone, PartialEq, Eq)] | 587 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -591,7 +592,7 @@ pub struct TypeAlias { | |||
591 | pub bounds: Box<[TypeBound]>, | 592 | pub bounds: Box<[TypeBound]>, |
592 | pub generic_params: GenericParamsId, | 593 | pub generic_params: GenericParamsId, |
593 | pub type_ref: Option<TypeRef>, | 594 | pub type_ref: Option<TypeRef>, |
594 | pub ast_id: FileAstId<ast::TypeAliasDef>, | 595 | pub ast_id: FileAstId<ast::TypeAlias>, |
595 | } | 596 | } |
596 | 597 | ||
597 | #[derive(Debug, Clone, Eq, PartialEq)] | 598 | #[derive(Debug, Clone, Eq, PartialEq)] |
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 5149dd141..feb31579e 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -1,10 +1,7 @@ | |||
1 | //! AST -> `ItemTree` lowering code. | 1 | //! AST -> `ItemTree` lowering code. |
2 | 2 | ||
3 | use super::*; | 3 | use std::{collections::hash_map::Entry, mem, sync::Arc}; |
4 | use crate::{ | 4 | |
5 | attr::Attrs, | ||
6 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | ||
7 | }; | ||
8 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; | 5 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; |
9 | use ra_arena::map::ArenaMap; | 6 | use ra_arena::map::ArenaMap; |
10 | use ra_syntax::{ | 7 | use ra_syntax::{ |
@@ -12,7 +9,13 @@ use ra_syntax::{ | |||
12 | SyntaxNode, | 9 | SyntaxNode, |
13 | }; | 10 | }; |
14 | use smallvec::SmallVec; | 11 | use smallvec::SmallVec; |
15 | use std::{collections::hash_map::Entry, mem, sync::Arc}; | 12 | |
13 | use crate::{ | ||
14 | attr::Attrs, | ||
15 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | ||
16 | }; | ||
17 | |||
18 | use super::*; | ||
16 | 19 | ||
17 | fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { | 20 | fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { |
18 | FileItemTreeId { index, _p: PhantomData } | 21 | FileItemTreeId { index, _p: PhantomData } |
@@ -70,19 +73,19 @@ impl Ctx { | |||
70 | self.tree.data_mut() | 73 | self.tree.data_mut() |
71 | } | 74 | } |
72 | 75 | ||
73 | fn lower_mod_item(&mut self, item: &ast::ModuleItem, inner: bool) -> Option<ModItems> { | 76 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { |
74 | assert!(inner || self.inner_items.is_empty()); | 77 | assert!(inner || self.inner_items.is_empty()); |
75 | 78 | ||
76 | // Collect inner items for 1-to-1-lowered items. | 79 | // Collect inner items for 1-to-1-lowered items. |
77 | match item { | 80 | match item { |
78 | ast::ModuleItem::StructDef(_) | 81 | ast::Item::Struct(_) |
79 | | ast::ModuleItem::UnionDef(_) | 82 | | ast::Item::Union(_) |
80 | | ast::ModuleItem::EnumDef(_) | 83 | | ast::Item::Enum(_) |
81 | | ast::ModuleItem::FnDef(_) | 84 | | ast::Item::Fn(_) |
82 | | ast::ModuleItem::TypeAliasDef(_) | 85 | | ast::Item::TypeAlias(_) |
83 | | ast::ModuleItem::ConstDef(_) | 86 | | ast::Item::Const(_) |
84 | | ast::ModuleItem::StaticDef(_) | 87 | | ast::Item::Static(_) |
85 | | ast::ModuleItem::MacroCall(_) => { | 88 | | ast::Item::MacroCall(_) => { |
86 | // Skip this if we're already collecting inner items. We'll descend into all nodes | 89 | // Skip this if we're already collecting inner items. We'll descend into all nodes |
87 | // already. | 90 | // already. |
88 | if !inner { | 91 | if !inner { |
@@ -92,34 +95,30 @@ impl Ctx { | |||
92 | 95 | ||
93 | // These are handled in their respective `lower_X` method (since we can't just blindly | 96 | // These are handled in their respective `lower_X` method (since we can't just blindly |
94 | // walk them). | 97 | // walk them). |
95 | ast::ModuleItem::TraitDef(_) | 98 | ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {} |
96 | | ast::ModuleItem::ImplDef(_) | ||
97 | | ast::ModuleItem::ExternBlock(_) => {} | ||
98 | 99 | ||
99 | // These don't have inner items. | 100 | // These don't have inner items. |
100 | ast::ModuleItem::Module(_) | 101 | ast::Item::Module(_) | ast::Item::ExternCrate(_) | ast::Item::Use(_) => {} |
101 | | ast::ModuleItem::ExternCrateItem(_) | ||
102 | | ast::ModuleItem::UseItem(_) => {} | ||
103 | }; | 102 | }; |
104 | 103 | ||
105 | let attrs = Attrs::new(item, &self.hygiene); | 104 | let attrs = Attrs::new(item, &self.hygiene); |
106 | let items = match item { | 105 | let items = match item { |
107 | ast::ModuleItem::StructDef(ast) => self.lower_struct(ast).map(Into::into), | 106 | ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into), |
108 | ast::ModuleItem::UnionDef(ast) => self.lower_union(ast).map(Into::into), | 107 | ast::Item::Union(ast) => self.lower_union(ast).map(Into::into), |
109 | ast::ModuleItem::EnumDef(ast) => self.lower_enum(ast).map(Into::into), | 108 | ast::Item::Enum(ast) => self.lower_enum(ast).map(Into::into), |
110 | ast::ModuleItem::FnDef(ast) => self.lower_function(ast).map(Into::into), | 109 | ast::Item::Fn(ast) => self.lower_function(ast).map(Into::into), |
111 | ast::ModuleItem::TypeAliasDef(ast) => self.lower_type_alias(ast).map(Into::into), | 110 | ast::Item::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into), |
112 | ast::ModuleItem::StaticDef(ast) => self.lower_static(ast).map(Into::into), | 111 | ast::Item::Static(ast) => self.lower_static(ast).map(Into::into), |
113 | ast::ModuleItem::ConstDef(ast) => Some(self.lower_const(ast).into()), | 112 | ast::Item::Const(ast) => Some(self.lower_const(ast).into()), |
114 | ast::ModuleItem::Module(ast) => self.lower_module(ast).map(Into::into), | 113 | ast::Item::Module(ast) => self.lower_module(ast).map(Into::into), |
115 | ast::ModuleItem::TraitDef(ast) => self.lower_trait(ast).map(Into::into), | 114 | ast::Item::Trait(ast) => self.lower_trait(ast).map(Into::into), |
116 | ast::ModuleItem::ImplDef(ast) => self.lower_impl(ast).map(Into::into), | 115 | ast::Item::Impl(ast) => self.lower_impl(ast).map(Into::into), |
117 | ast::ModuleItem::UseItem(ast) => Some(ModItems( | 116 | ast::Item::Use(ast) => Some(ModItems( |
118 | self.lower_use(ast).into_iter().map(Into::into).collect::<SmallVec<_>>(), | 117 | self.lower_use(ast).into_iter().map(Into::into).collect::<SmallVec<_>>(), |
119 | )), | 118 | )), |
120 | ast::ModuleItem::ExternCrateItem(ast) => self.lower_extern_crate(ast).map(Into::into), | 119 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), |
121 | ast::ModuleItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), | 120 | ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |
122 | ast::ModuleItem::ExternBlock(ast) => { | 121 | ast::Item::ExternBlock(ast) => { |
123 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) | 122 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) |
124 | } | 123 | } |
125 | }; | 124 | }; |
@@ -147,27 +146,26 @@ impl Ctx { | |||
147 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 146 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
148 | let forced_vis = self.forced_visibility.take(); | 147 | let forced_vis = self.forced_visibility.take(); |
149 | let mut inner_items = mem::take(&mut self.tree.inner_items); | 148 | let mut inner_items = mem::take(&mut self.tree.inner_items); |
150 | inner_items.extend( | 149 | inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( |
151 | container.descendants().skip(1).filter_map(ast::ModuleItem::cast).filter_map(|item| { | 150 | |item| { |
152 | let ast_id = self.source_ast_id_map.ast_id(&item); | 151 | let ast_id = self.source_ast_id_map.ast_id(&item); |
153 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | 152 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) |
154 | }), | 153 | }, |
155 | ); | 154 | )); |
156 | self.tree.inner_items = inner_items; | 155 | self.tree.inner_items = inner_items; |
157 | self.forced_visibility = forced_vis; | 156 | self.forced_visibility = forced_vis; |
158 | } | 157 | } |
159 | 158 | ||
160 | fn lower_assoc_item(&mut self, item: &ast::ModuleItem) -> Option<AssocItem> { | 159 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { |
161 | match item { | 160 | match item { |
162 | ast::ModuleItem::FnDef(ast) => self.lower_function(ast).map(Into::into), | 161 | ast::AssocItem::Fn(ast) => self.lower_function(ast).map(Into::into), |
163 | ast::ModuleItem::TypeAliasDef(ast) => self.lower_type_alias(ast).map(Into::into), | 162 | ast::AssocItem::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into), |
164 | ast::ModuleItem::ConstDef(ast) => Some(self.lower_const(ast).into()), | 163 | ast::AssocItem::Const(ast) => Some(self.lower_const(ast).into()), |
165 | ast::ModuleItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), | 164 | ast::AssocItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |
166 | _ => None, | ||
167 | } | 165 | } |
168 | } | 166 | } |
169 | 167 | ||
170 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<FileItemTreeId<Struct>> { | 168 | fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> { |
171 | let visibility = self.lower_visibility(strukt); | 169 | let visibility = self.lower_visibility(strukt); |
172 | let name = strukt.name()?.as_name(); | 170 | let name = strukt.name()?.as_name(); |
173 | let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); | 171 | let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); |
@@ -196,7 +194,7 @@ impl Ctx { | |||
196 | } | 194 | } |
197 | } | 195 | } |
198 | 196 | ||
199 | fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> IdRange<Field> { | 197 | fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdRange<Field> { |
200 | let start = self.next_field_idx(); | 198 | let start = self.next_field_idx(); |
201 | for field in fields.fields() { | 199 | for field in fields.fields() { |
202 | if let Some(data) = self.lower_record_field(&field) { | 200 | if let Some(data) = self.lower_record_field(&field) { |
@@ -208,42 +206,39 @@ impl Ctx { | |||
208 | IdRange::new(start..end) | 206 | IdRange::new(start..end) |
209 | } | 207 | } |
210 | 208 | ||
211 | fn lower_record_field(&mut self, field: &ast::RecordFieldDef) -> Option<Field> { | 209 | fn lower_record_field(&mut self, field: &ast::RecordField) -> Option<Field> { |
212 | let name = field.name()?.as_name(); | 210 | let name = field.name()?.as_name(); |
213 | let visibility = self.lower_visibility(field); | 211 | let visibility = self.lower_visibility(field); |
214 | let type_ref = self.lower_type_ref(&field.ascribed_type()?); | 212 | let type_ref = self.lower_type_ref_opt(field.ty()); |
215 | let res = Field { name, type_ref, visibility }; | 213 | let res = Field { name, type_ref, visibility }; |
216 | Some(res) | 214 | Some(res) |
217 | } | 215 | } |
218 | 216 | ||
219 | fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> IdRange<Field> { | 217 | fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdRange<Field> { |
220 | let start = self.next_field_idx(); | 218 | let start = self.next_field_idx(); |
221 | for (i, field) in fields.fields().enumerate() { | 219 | for (i, field) in fields.fields().enumerate() { |
222 | if let Some(data) = self.lower_tuple_field(i, &field) { | 220 | let data = self.lower_tuple_field(i, &field); |
223 | let idx = self.data().fields.alloc(data); | 221 | let idx = self.data().fields.alloc(data); |
224 | self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); | 222 | self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); |
225 | } | ||
226 | } | 223 | } |
227 | let end = self.next_field_idx(); | 224 | let end = self.next_field_idx(); |
228 | IdRange::new(start..end) | 225 | IdRange::new(start..end) |
229 | } | 226 | } |
230 | 227 | ||
231 | fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleFieldDef) -> Option<Field> { | 228 | fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field { |
232 | let name = Name::new_tuple_field(idx); | 229 | let name = Name::new_tuple_field(idx); |
233 | let visibility = self.lower_visibility(field); | 230 | let visibility = self.lower_visibility(field); |
234 | let type_ref = self.lower_type_ref(&field.type_ref()?); | 231 | let type_ref = self.lower_type_ref_opt(field.ty()); |
235 | let res = Field { name, type_ref, visibility }; | 232 | let res = Field { name, type_ref, visibility }; |
236 | Some(res) | 233 | res |
237 | } | 234 | } |
238 | 235 | ||
239 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<FileItemTreeId<Union>> { | 236 | fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> { |
240 | let visibility = self.lower_visibility(union); | 237 | let visibility = self.lower_visibility(union); |
241 | let name = union.name()?.as_name(); | 238 | let name = union.name()?.as_name(); |
242 | let generic_params = self.lower_generic_params(GenericsOwner::Union, union); | 239 | let generic_params = self.lower_generic_params(GenericsOwner::Union, union); |
243 | let fields = match union.record_field_def_list() { | 240 | let fields = match union.record_field_list() { |
244 | Some(record_field_def_list) => { | 241 | Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)), |
245 | self.lower_fields(&StructKind::Record(record_field_def_list)) | ||
246 | } | ||
247 | None => Fields::Record(IdRange::new(self.next_field_idx()..self.next_field_idx())), | 242 | None => Fields::Record(IdRange::new(self.next_field_idx()..self.next_field_idx())), |
248 | }; | 243 | }; |
249 | let ast_id = self.source_ast_id_map.ast_id(union); | 244 | let ast_id = self.source_ast_id_map.ast_id(union); |
@@ -251,7 +246,7 @@ impl Ctx { | |||
251 | Some(id(self.data().unions.alloc(res))) | 246 | Some(id(self.data().unions.alloc(res))) |
252 | } | 247 | } |
253 | 248 | ||
254 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<FileItemTreeId<Enum>> { | 249 | fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> { |
255 | let visibility = self.lower_visibility(enum_); | 250 | let visibility = self.lower_visibility(enum_); |
256 | let name = enum_.name()?.as_name(); | 251 | let name = enum_.name()?.as_name(); |
257 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); | 252 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); |
@@ -264,7 +259,7 @@ impl Ctx { | |||
264 | Some(id(self.data().enums.alloc(res))) | 259 | Some(id(self.data().enums.alloc(res))) |
265 | } | 260 | } |
266 | 261 | ||
267 | fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> IdRange<Variant> { | 262 | fn lower_variants(&mut self, variants: &ast::VariantList) -> IdRange<Variant> { |
268 | let start = self.next_variant_idx(); | 263 | let start = self.next_variant_idx(); |
269 | for variant in variants.variants() { | 264 | for variant in variants.variants() { |
270 | if let Some(data) = self.lower_variant(&variant) { | 265 | if let Some(data) = self.lower_variant(&variant) { |
@@ -276,14 +271,14 @@ impl Ctx { | |||
276 | IdRange::new(start..end) | 271 | IdRange::new(start..end) |
277 | } | 272 | } |
278 | 273 | ||
279 | fn lower_variant(&mut self, variant: &ast::EnumVariant) -> Option<Variant> { | 274 | fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> { |
280 | let name = variant.name()?.as_name(); | 275 | let name = variant.name()?.as_name(); |
281 | let fields = self.lower_fields(&variant.kind()); | 276 | let fields = self.lower_fields(&variant.kind()); |
282 | let res = Variant { name, fields }; | 277 | let res = Variant { name, fields }; |
283 | Some(res) | 278 | Some(res) |
284 | } | 279 | } |
285 | 280 | ||
286 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<FileItemTreeId<Function>> { | 281 | fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> { |
287 | let visibility = self.lower_visibility(func); | 282 | let visibility = self.lower_visibility(func); |
288 | let name = func.name()?.as_name(); | 283 | let name = func.name()?.as_name(); |
289 | 284 | ||
@@ -291,7 +286,7 @@ impl Ctx { | |||
291 | let mut has_self_param = false; | 286 | let mut has_self_param = false; |
292 | if let Some(param_list) = func.param_list() { | 287 | if let Some(param_list) = func.param_list() { |
293 | if let Some(self_param) = param_list.self_param() { | 288 | if let Some(self_param) = param_list.self_param() { |
294 | let self_type = match self_param.ascribed_type() { | 289 | let self_type = match self_param.ty() { |
295 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), | 290 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), |
296 | None => { | 291 | None => { |
297 | let self_type = TypeRef::Path(name![Self].into()); | 292 | let self_type = TypeRef::Path(name![Self].into()); |
@@ -310,11 +305,19 @@ impl Ctx { | |||
310 | has_self_param = true; | 305 | has_self_param = true; |
311 | } | 306 | } |
312 | for param in param_list.params() { | 307 | for param in param_list.params() { |
313 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ascribed_type()); | 308 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); |
314 | params.push(type_ref); | 309 | params.push(type_ref); |
315 | } | 310 | } |
316 | } | 311 | } |
317 | let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) { | 312 | |
313 | let mut is_varargs = false; | ||
314 | if let Some(params) = func.param_list() { | ||
315 | if let Some(last) = params.params().last() { | ||
316 | is_varargs = last.dotdotdot_token().is_some(); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | let ret_type = match func.ret_type().and_then(|rt| rt.ty()) { | ||
318 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), | 321 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), |
319 | _ => TypeRef::unit(), | 322 | _ => TypeRef::unit(), |
320 | }; | 323 | }; |
@@ -335,6 +338,7 @@ impl Ctx { | |||
335 | has_self_param, | 338 | has_self_param, |
336 | is_unsafe: func.unsafe_token().is_some(), | 339 | is_unsafe: func.unsafe_token().is_some(), |
337 | params: params.into_boxed_slice(), | 340 | params: params.into_boxed_slice(), |
341 | is_varargs, | ||
338 | ret_type, | 342 | ret_type, |
339 | ast_id, | 343 | ast_id, |
340 | }; | 344 | }; |
@@ -345,10 +349,10 @@ impl Ctx { | |||
345 | 349 | ||
346 | fn lower_type_alias( | 350 | fn lower_type_alias( |
347 | &mut self, | 351 | &mut self, |
348 | type_alias: &ast::TypeAliasDef, | 352 | type_alias: &ast::TypeAlias, |
349 | ) -> Option<FileItemTreeId<TypeAlias>> { | 353 | ) -> Option<FileItemTreeId<TypeAlias>> { |
350 | let name = type_alias.name()?.as_name(); | 354 | let name = type_alias.name()?.as_name(); |
351 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); | 355 | let type_ref = type_alias.ty().map(|it| self.lower_type_ref(&it)); |
352 | let visibility = self.lower_visibility(type_alias); | 356 | let visibility = self.lower_visibility(type_alias); |
353 | let bounds = self.lower_type_bounds(type_alias); | 357 | let bounds = self.lower_type_bounds(type_alias); |
354 | let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias); | 358 | let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias); |
@@ -364,9 +368,9 @@ impl Ctx { | |||
364 | Some(id(self.data().type_aliases.alloc(res))) | 368 | Some(id(self.data().type_aliases.alloc(res))) |
365 | } | 369 | } |
366 | 370 | ||
367 | fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<FileItemTreeId<Static>> { | 371 | fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> { |
368 | let name = static_.name()?.as_name(); | 372 | let name = static_.name()?.as_name(); |
369 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); | 373 | let type_ref = self.lower_type_ref_opt(static_.ty()); |
370 | let visibility = self.lower_visibility(static_); | 374 | let visibility = self.lower_visibility(static_); |
371 | let mutable = static_.mut_token().is_some(); | 375 | let mutable = static_.mut_token().is_some(); |
372 | let ast_id = self.source_ast_id_map.ast_id(static_); | 376 | let ast_id = self.source_ast_id_map.ast_id(static_); |
@@ -374,9 +378,9 @@ impl Ctx { | |||
374 | Some(id(self.data().statics.alloc(res))) | 378 | Some(id(self.data().statics.alloc(res))) |
375 | } | 379 | } |
376 | 380 | ||
377 | fn lower_const(&mut self, konst: &ast::ConstDef) -> FileItemTreeId<Const> { | 381 | fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> { |
378 | let name = konst.name().map(|it| it.as_name()); | 382 | let name = konst.name().map(|it| it.as_name()); |
379 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); | 383 | let type_ref = self.lower_type_ref_opt(konst.ty()); |
380 | let visibility = self.lower_visibility(konst); | 384 | let visibility = self.lower_visibility(konst); |
381 | let ast_id = self.source_ast_id_map.ast_id(konst); | 385 | let ast_id = self.source_ast_id_map.ast_id(konst); |
382 | let res = Const { name, visibility, type_ref, ast_id }; | 386 | let res = Const { name, visibility, type_ref, ast_id }; |
@@ -409,15 +413,15 @@ impl Ctx { | |||
409 | Some(id(self.data().mods.alloc(res))) | 413 | Some(id(self.data().mods.alloc(res))) |
410 | } | 414 | } |
411 | 415 | ||
412 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<FileItemTreeId<Trait>> { | 416 | fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> { |
413 | let name = trait_def.name()?.as_name(); | 417 | let name = trait_def.name()?.as_name(); |
414 | let visibility = self.lower_visibility(trait_def); | 418 | let visibility = self.lower_visibility(trait_def); |
415 | let generic_params = | 419 | let generic_params = |
416 | self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); | 420 | self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); |
417 | let auto = trait_def.auto_token().is_some(); | 421 | let auto = trait_def.auto_token().is_some(); |
418 | let items = trait_def.item_list().map(|list| { | 422 | let items = trait_def.assoc_item_list().map(|list| { |
419 | self.with_inherited_visibility(visibility, |this| { | 423 | self.with_inherited_visibility(visibility, |this| { |
420 | list.items() | 424 | list.assoc_items() |
421 | .filter_map(|item| { | 425 | .filter_map(|item| { |
422 | let attrs = Attrs::new(&item, &this.hygiene); | 426 | let attrs = Attrs::new(&item, &this.hygiene); |
423 | this.collect_inner_items(item.syntax()); | 427 | this.collect_inner_items(item.syntax()); |
@@ -441,7 +445,7 @@ impl Ctx { | |||
441 | Some(id(self.data().traits.alloc(res))) | 445 | Some(id(self.data().traits.alloc(res))) |
442 | } | 446 | } |
443 | 447 | ||
444 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<FileItemTreeId<Impl>> { | 448 | fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { |
445 | let generic_params = | 449 | let generic_params = |
446 | self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); | 450 | self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); |
447 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); | 451 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); |
@@ -450,8 +454,9 @@ impl Ctx { | |||
450 | 454 | ||
451 | // We cannot use `assoc_items()` here as that does not include macro calls. | 455 | // We cannot use `assoc_items()` here as that does not include macro calls. |
452 | let items = impl_def | 456 | let items = impl_def |
453 | .item_list()? | 457 | .assoc_item_list() |
454 | .items() | 458 | .into_iter() |
459 | .flat_map(|it| it.assoc_items()) | ||
455 | .filter_map(|item| { | 460 | .filter_map(|item| { |
456 | self.collect_inner_items(item.syntax()); | 461 | self.collect_inner_items(item.syntax()); |
457 | let assoc = self.lower_assoc_item(&item)?; | 462 | let assoc = self.lower_assoc_item(&item)?; |
@@ -465,7 +470,7 @@ impl Ctx { | |||
465 | Some(id(self.data().impls.alloc(res))) | 470 | Some(id(self.data().impls.alloc(res))) |
466 | } | 471 | } |
467 | 472 | ||
468 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<FileItemTreeId<Import>> { | 473 | fn lower_use(&mut self, use_item: &ast::Use) -> Vec<FileItemTreeId<Import>> { |
469 | // FIXME: cfg_attr | 474 | // FIXME: cfg_attr |
470 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 475 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
471 | let visibility = self.lower_visibility(use_item); | 476 | let visibility = self.lower_visibility(use_item); |
@@ -494,10 +499,10 @@ impl Ctx { | |||
494 | 499 | ||
495 | fn lower_extern_crate( | 500 | fn lower_extern_crate( |
496 | &mut self, | 501 | &mut self, |
497 | extern_crate: &ast::ExternCrateItem, | 502 | extern_crate: &ast::ExternCrate, |
498 | ) -> Option<FileItemTreeId<ExternCrate>> { | 503 | ) -> Option<FileItemTreeId<ExternCrate>> { |
499 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); | 504 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); |
500 | let alias = extern_crate.alias().map(|a| { | 505 | let alias = extern_crate.rename().map(|a| { |
501 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | 506 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) |
502 | }); | 507 | }); |
503 | let visibility = self.lower_visibility(extern_crate); | 508 | let visibility = self.lower_visibility(extern_crate); |
@@ -543,14 +548,16 @@ impl Ctx { | |||
543 | self.collect_inner_items(item.syntax()); | 548 | self.collect_inner_items(item.syntax()); |
544 | let attrs = Attrs::new(&item, &self.hygiene); | 549 | let attrs = Attrs::new(&item, &self.hygiene); |
545 | let id: ModItem = match item { | 550 | let id: ModItem = match item { |
546 | ast::ExternItem::FnDef(ast) => { | 551 | ast::ExternItem::Fn(ast) => { |
547 | let func = self.lower_function(&ast)?; | 552 | let func = self.lower_function(&ast)?; |
553 | self.data().functions[func.index].is_unsafe = true; | ||
548 | func.into() | 554 | func.into() |
549 | } | 555 | } |
550 | ast::ExternItem::StaticDef(ast) => { | 556 | ast::ExternItem::Static(ast) => { |
551 | let statik = self.lower_static(&ast)?; | 557 | let statik = self.lower_static(&ast)?; |
552 | statik.into() | 558 | statik.into() |
553 | } | 559 | } |
560 | ast::ExternItem::MacroCall(_) => return None, | ||
554 | }; | 561 | }; |
555 | self.add_attrs(id.into(), attrs); | 562 | self.add_attrs(id.into(), attrs); |
556 | Some(id) | 563 | Some(id) |
@@ -563,10 +570,10 @@ impl Ctx { | |||
563 | fn lower_generic_params_and_inner_items( | 570 | fn lower_generic_params_and_inner_items( |
564 | &mut self, | 571 | &mut self, |
565 | owner: GenericsOwner<'_>, | 572 | owner: GenericsOwner<'_>, |
566 | node: &impl ast::TypeParamsOwner, | 573 | node: &impl ast::GenericParamsOwner, |
567 | ) -> GenericParamsId { | 574 | ) -> GenericParamsId { |
568 | // Generics are part of item headers and may contain inner items we need to collect. | 575 | // Generics are part of item headers and may contain inner items we need to collect. |
569 | if let Some(params) = node.type_param_list() { | 576 | if let Some(params) = node.generic_param_list() { |
570 | self.collect_inner_items(params.syntax()); | 577 | self.collect_inner_items(params.syntax()); |
571 | } | 578 | } |
572 | if let Some(clause) = node.where_clause() { | 579 | if let Some(clause) = node.where_clause() { |
@@ -579,7 +586,7 @@ impl Ctx { | |||
579 | fn lower_generic_params( | 586 | fn lower_generic_params( |
580 | &mut self, | 587 | &mut self, |
581 | owner: GenericsOwner<'_>, | 588 | owner: GenericsOwner<'_>, |
582 | node: &impl ast::TypeParamsOwner, | 589 | node: &impl ast::GenericParamsOwner, |
583 | ) -> GenericParamsId { | 590 | ) -> GenericParamsId { |
584 | let mut sm = &mut ArenaMap::default(); | 591 | let mut sm = &mut ArenaMap::default(); |
585 | let mut generics = GenericParams::default(); | 592 | let mut generics = GenericParams::default(); |
@@ -692,7 +699,7 @@ enum GenericsOwner<'a> { | |||
692 | Enum, | 699 | Enum, |
693 | Union, | 700 | Union, |
694 | /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter. | 701 | /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter. |
695 | Trait(&'a ast::TraitDef), | 702 | Trait(&'a ast::Trait), |
696 | TypeAlias, | 703 | TypeAlias, |
697 | Impl, | 704 | Impl, |
698 | } | 705 | } |
diff --git a/crates/ra_hir_def/src/item_tree/tests.rs b/crates/ra_hir_def/src/item_tree/tests.rs index 08559fb92..a81497fa8 100644 --- a/crates/ra_hir_def/src/item_tree/tests.rs +++ b/crates/ra_hir_def/src/item_tree/tests.rs | |||
@@ -1,13 +1,15 @@ | |||
1 | use super::{ItemTree, ModItem, ModKind}; | 1 | use expect::{expect, Expect}; |
2 | use crate::{db::DefDatabase, test_db::TestDB}; | ||
3 | use hir_expand::{db::AstDatabase, HirFileId, InFile}; | 2 | use hir_expand::{db::AstDatabase, HirFileId, InFile}; |
4 | use insta::assert_snapshot; | ||
5 | use ra_db::fixture::WithFixture; | 3 | use ra_db::fixture::WithFixture; |
6 | use ra_syntax::{ast, AstNode}; | 4 | use ra_syntax::{ast, AstNode}; |
7 | use rustc_hash::FxHashSet; | 5 | use rustc_hash::FxHashSet; |
8 | use std::sync::Arc; | 6 | use std::sync::Arc; |
9 | use stdx::format_to; | 7 | use stdx::format_to; |
10 | 8 | ||
9 | use crate::{db::DefDatabase, test_db::TestDB}; | ||
10 | |||
11 | use super::{ItemTree, ModItem, ModKind}; | ||
12 | |||
11 | fn test_inner_items(ra_fixture: &str) { | 13 | fn test_inner_items(ra_fixture: &str) { |
12 | let (db, file_id) = TestDB::with_single_file(ra_fixture); | 14 | let (db, file_id) = TestDB::with_single_file(ra_fixture); |
13 | let file_id = HirFileId::from(file_id); | 15 | let file_id = HirFileId::from(file_id); |
@@ -19,7 +21,7 @@ fn test_inner_items(ra_fixture: &str) { | |||
19 | let mut outer_items = FxHashSet::default(); | 21 | let mut outer_items = FxHashSet::default(); |
20 | let mut worklist = tree.top_level_items().to_vec(); | 22 | let mut worklist = tree.top_level_items().to_vec(); |
21 | while let Some(item) = worklist.pop() { | 23 | while let Some(item) = worklist.pop() { |
22 | let node: ast::ModuleItem = match item { | 24 | let node: ast::Item = match item { |
23 | ModItem::Import(it) => tree.source(&db, InFile::new(file_id, it)).into(), | 25 | ModItem::Import(it) => tree.source(&db, InFile::new(file_id, it)).into(), |
24 | ModItem::ExternCrate(it) => tree.source(&db, InFile::new(file_id, it)).into(), | 26 | ModItem::ExternCrate(it) => tree.source(&db, InFile::new(file_id, it)).into(), |
25 | ModItem::Function(it) => tree.source(&db, InFile::new(file_id, it)).into(), | 27 | ModItem::Function(it) => tree.source(&db, InFile::new(file_id, it)).into(), |
@@ -51,7 +53,7 @@ fn test_inner_items(ra_fixture: &str) { | |||
51 | 53 | ||
52 | // Now descend the root node and check that all `ast::ModuleItem`s are either recorded above, or | 54 | // Now descend the root node and check that all `ast::ModuleItem`s are either recorded above, or |
53 | // registered as inner items. | 55 | // registered as inner items. |
54 | for item in root.descendants().skip(1).filter_map(ast::ModuleItem::cast) { | 56 | for item in root.descendants().skip(1).filter_map(ast::Item::cast) { |
55 | if outer_items.contains(&item) { | 57 | if outer_items.contains(&item) { |
56 | continue; | 58 | continue; |
57 | } | 59 | } |
@@ -162,9 +164,15 @@ fn fmt_mod_item(out: &mut String, tree: &ItemTree, item: ModItem) { | |||
162 | } | 164 | } |
163 | } | 165 | } |
164 | 166 | ||
167 | fn check(ra_fixture: &str, expect: Expect) { | ||
168 | let actual = print_item_tree(ra_fixture); | ||
169 | expect.assert_eq(&actual); | ||
170 | } | ||
171 | |||
165 | #[test] | 172 | #[test] |
166 | fn smoke() { | 173 | fn smoke() { |
167 | assert_snapshot!(print_item_tree(r" | 174 | check( |
175 | r" | ||
168 | #![attr] | 176 | #![attr] |
169 | 177 | ||
170 | #[attr_on_use] | 178 | #[attr_on_use] |
@@ -214,42 +222,44 @@ fn smoke() { | |||
214 | #[union_fld] | 222 | #[union_fld] |
215 | fld: u16, | 223 | fld: u16, |
216 | } | 224 | } |
217 | "), @r###" | 225 | ", |
218 | inner attrs: Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr"))] }, input: None }]) } | 226 | expect![[r##" |
219 | 227 | inner attrs: Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr"))] }, input: None }]) } | |
220 | top-level items: | 228 | |
221 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }] | 229 | top-level items: |
222 | Import { path: ModPath { kind: Plain, segments: [Name(Text("a"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: false, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::UseItem>(0) } | 230 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }] |
223 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }] | 231 | Import { path: ModPath { kind: Plain, segments: [Name(Text("a"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: false, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Use>(0) } |
224 | Import { path: ModPath { kind: Plain, segments: [Name(Text("b"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: true, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::UseItem>(0) } | 232 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }] |
225 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("ext_crate"))] }, input: None }]) }] | 233 | Import { path: ModPath { kind: Plain, segments: [Name(Text("b"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: true, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Use>(0) } |
226 | ExternCrate { path: ModPath { kind: Plain, segments: [Name(Text("krate"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ExternCrateItem>(1) } | 234 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("ext_crate"))] }, input: None }]) }] |
227 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }] | 235 | ExternCrate { path: ModPath { kind: Plain, segments: [Name(Text("krate"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ExternCrate>(1) } |
228 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TraitDef>(2) } | 236 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }] |
229 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }] | 237 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Trait>(2) } |
230 | > TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TypeAliasDef>(8) } | 238 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }] |
231 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }] | 239 | > TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TypeAlias>(8) } |
232 | > Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ConstDef>(9) } | 240 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }] |
233 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }] | 241 | > Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Const>(9) } |
234 | > Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(10) } | 242 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }] |
235 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_dfl_method"))] }, input: None }]) }] | 243 | > Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(10) } |
236 | > Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(11) } | 244 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_dfl_method"))] }, input: None }]) }] |
237 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }] | 245 | > Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(11) } |
238 | Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(3), kind: Unit } | 246 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }] |
239 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }] | 247 | Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Struct>(3), kind: Unit } |
240 | Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(IdRange::<ra_hir_def::item_tree::Field>(0..1)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(4), kind: Tuple } | 248 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }] |
241 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct2"))] }, input: None }]) }] | 249 | Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(IdRange::<ra_hir_def::item_tree::Field>(0..1)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Struct>(4), kind: Tuple } |
242 | Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(1..2)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(5), kind: Record } | 250 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct2"))] }, input: None }]) }] |
243 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("en"))] }, input: None }]) }] | 251 | Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(1..2)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Struct>(5), kind: Record } |
244 | Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: IdRange::<ra_hir_def::item_tree::Variant>(0..1), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::EnumDef>(6) } | 252 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("en"))] }, input: None }]) }] |
245 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("un"))] }, input: None }]) }] | 253 | Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: IdRange::<ra_hir_def::item_tree::Variant>(0..1), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Enum>(6) } |
246 | Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(3..4)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::UnionDef>(7) } | 254 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("un"))] }, input: None }]) }] |
247 | "###); | 255 | Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(3..4)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Union>(7) } |
256 | "##]], | ||
257 | ); | ||
248 | } | 258 | } |
249 | 259 | ||
250 | #[test] | 260 | #[test] |
251 | fn simple_inner_items() { | 261 | fn simple_inner_items() { |
252 | let tree = print_item_tree( | 262 | check( |
253 | r" | 263 | r" |
254 | impl<T:A> D for Response<T> { | 264 | impl<T:A> D for Response<T> { |
255 | fn foo() { | 265 | fn foo() { |
@@ -260,26 +270,25 @@ fn simple_inner_items() { | |||
260 | } | 270 | } |
261 | } | 271 | } |
262 | ", | 272 | ", |
263 | ); | 273 | expect![[r#" |
274 | inner attrs: Attrs { entries: None } | ||
264 | 275 | ||
265 | assert_snapshot!(tree, @r###" | 276 | top-level items: |
266 | inner attrs: Attrs { entries: None } | 277 | Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Impl>(0) } |
278 | > Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) } | ||
267 | 279 | ||
268 | top-level items: | 280 | inner items: |
269 | Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) } | ||
270 | > Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) } | ||
271 | 281 | ||
272 | inner items: | 282 | for AST FileAstId::<ra_syntax::ast::generated::nodes::Item>(2): |
283 | Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) } | ||
273 | 284 | ||
274 | for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2): | 285 | "#]], |
275 | Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) } | 286 | ); |
276 | |||
277 | "###); | ||
278 | } | 287 | } |
279 | 288 | ||
280 | #[test] | 289 | #[test] |
281 | fn extern_attrs() { | 290 | fn extern_attrs() { |
282 | let tree = print_item_tree( | 291 | check( |
283 | r#" | 292 | r#" |
284 | #[block_attr] | 293 | #[block_attr] |
285 | extern "C" { | 294 | extern "C" { |
@@ -289,22 +298,21 @@ fn extern_attrs() { | |||
289 | fn b() {} | 298 | fn b() {} |
290 | } | 299 | } |
291 | "#, | 300 | "#, |
301 | expect![[r##" | ||
302 | inner attrs: Attrs { entries: None } | ||
303 | |||
304 | top-level items: | ||
305 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }] | ||
306 | Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) } | ||
307 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }] | ||
308 | Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) } | ||
309 | "##]], | ||
292 | ); | 310 | ); |
293 | |||
294 | assert_snapshot!(tree, @r###" | ||
295 | inner attrs: Attrs { entries: None } | ||
296 | |||
297 | top-level items: | ||
298 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }] | ||
299 | Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) } | ||
300 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }] | ||
301 | Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) } | ||
302 | "###); | ||
303 | } | 311 | } |
304 | 312 | ||
305 | #[test] | 313 | #[test] |
306 | fn trait_attrs() { | 314 | fn trait_attrs() { |
307 | let tree = print_item_tree( | 315 | check( |
308 | r#" | 316 | r#" |
309 | #[trait_attr] | 317 | #[trait_attr] |
310 | trait Tr { | 318 | trait Tr { |
@@ -314,24 +322,23 @@ fn trait_attrs() { | |||
314 | fn b() {} | 322 | fn b() {} |
315 | } | 323 | } |
316 | "#, | 324 | "#, |
325 | expect![[r##" | ||
326 | inner attrs: Attrs { entries: None } | ||
327 | |||
328 | top-level items: | ||
329 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("trait_attr"))] }, input: None }]) }] | ||
330 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Trait>(0) } | ||
331 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }] | ||
332 | > Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) } | ||
333 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }] | ||
334 | > Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) } | ||
335 | "##]], | ||
317 | ); | 336 | ); |
318 | |||
319 | assert_snapshot!(tree, @r###" | ||
320 | inner attrs: Attrs { entries: None } | ||
321 | |||
322 | top-level items: | ||
323 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("trait_attr"))] }, input: None }]) }] | ||
324 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TraitDef>(0) } | ||
325 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }] | ||
326 | > Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) } | ||
327 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }] | ||
328 | > Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) } | ||
329 | "###); | ||
330 | } | 337 | } |
331 | 338 | ||
332 | #[test] | 339 | #[test] |
333 | fn impl_attrs() { | 340 | fn impl_attrs() { |
334 | let tree = print_item_tree( | 341 | check( |
335 | r#" | 342 | r#" |
336 | #[impl_attr] | 343 | #[impl_attr] |
337 | impl Ty { | 344 | impl Ty { |
@@ -341,19 +348,18 @@ fn impl_attrs() { | |||
341 | fn b() {} | 348 | fn b() {} |
342 | } | 349 | } |
343 | "#, | 350 | "#, |
351 | expect![[r##" | ||
352 | inner attrs: Attrs { entries: None } | ||
353 | |||
354 | top-level items: | ||
355 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("impl_attr"))] }, input: None }]) }] | ||
356 | Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Impl>(0) } | ||
357 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }] | ||
358 | > Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) } | ||
359 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }] | ||
360 | > Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) } | ||
361 | "##]], | ||
344 | ); | 362 | ); |
345 | |||
346 | assert_snapshot!(tree, @r###" | ||
347 | inner attrs: Attrs { entries: None } | ||
348 | |||
349 | top-level items: | ||
350 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("impl_attr"))] }, input: None }]) }] | ||
351 | Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) } | ||
352 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }] | ||
353 | > Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) } | ||
354 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }] | ||
355 | > Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) } | ||
356 | "###); | ||
357 | } | 363 | } |
358 | 364 | ||
359 | #[test] | 365 | #[test] |
@@ -391,45 +397,43 @@ fn cursed_inner_items() { | |||
391 | 397 | ||
392 | #[test] | 398 | #[test] |
393 | fn inner_item_attrs() { | 399 | fn inner_item_attrs() { |
394 | let tree = print_item_tree( | 400 | check( |
395 | r" | 401 | r" |
396 | fn foo() { | 402 | fn foo() { |
397 | #[on_inner] | 403 | #[on_inner] |
398 | fn inner() {} | 404 | fn inner() {} |
399 | } | 405 | } |
400 | ", | 406 | ", |
401 | ); | 407 | expect![[r##" |
402 | 408 | inner attrs: Attrs { entries: None } | |
403 | assert_snapshot!(tree, @r###" | ||
404 | inner attrs: Attrs { entries: None } | ||
405 | 409 | ||
406 | top-level items: | 410 | top-level items: |
407 | Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(0) } | 411 | Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(0) } |
408 | 412 | ||
409 | inner items: | 413 | inner items: |
410 | 414 | ||
411 | for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(1): | 415 | for AST FileAstId::<ra_syntax::ast::generated::nodes::Item>(1): |
412 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_inner"))] }, input: None }]) }] | 416 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_inner"))] }, input: None }]) }] |
413 | Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) } | 417 | Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) } |
414 | 418 | ||
415 | "###); | 419 | "##]], |
420 | ); | ||
416 | } | 421 | } |
417 | 422 | ||
418 | #[test] | 423 | #[test] |
419 | fn assoc_item_macros() { | 424 | fn assoc_item_macros() { |
420 | let tree = print_item_tree( | 425 | check( |
421 | r" | 426 | r" |
422 | impl S { | 427 | impl S { |
423 | items!(); | 428 | items!(); |
424 | } | 429 | } |
425 | ", | 430 | ", |
426 | ); | 431 | expect![[r#" |
427 | 432 | inner attrs: Attrs { entries: None } | |
428 | assert_snapshot!(tree, @r###" | ||
429 | inner attrs: Attrs { entries: None } | ||
430 | 433 | ||
431 | top-level items: | 434 | top-level items: |
432 | Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("S"))] }, generic_args: [None] }), is_negative: false, items: [MacroCall(Idx::<MacroCall>(0))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) } | 435 | Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("S"))] }, generic_args: [None] }), is_negative: false, items: [MacroCall(Idx::<MacroCall>(0))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Impl>(0) } |
433 | > MacroCall { name: None, path: ModPath { kind: Plain, segments: [Name(Text("items"))] }, is_export: false, is_local_inner: false, is_builtin: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::MacroCall>(1) } | 436 | > MacroCall { name: None, path: ModPath { kind: Plain, segments: [Name(Text("items"))] }, is_export: false, is_local_inner: false, is_builtin: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::MacroCall>(1) } |
434 | "###); | 437 | "#]], |
438 | ); | ||
435 | } | 439 | } |
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index a7349a21d..441bdbead 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs | |||
@@ -14,19 +14,19 @@ use crate::{ | |||
14 | 14 | ||
15 | pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; | 15 | pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; |
16 | 16 | ||
17 | pub const FUNCTION: Key<ast::FnDef, FunctionId> = Key::new(); | 17 | pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new(); |
18 | pub const CONST: Key<ast::ConstDef, ConstId> = Key::new(); | 18 | pub const CONST: Key<ast::Const, ConstId> = Key::new(); |
19 | pub const STATIC: Key<ast::StaticDef, StaticId> = Key::new(); | 19 | pub const STATIC: Key<ast::Static, StaticId> = Key::new(); |
20 | pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new(); | 20 | pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new(); |
21 | pub const IMPL: Key<ast::ImplDef, ImplId> = Key::new(); | 21 | pub const IMPL: Key<ast::Impl, ImplId> = Key::new(); |
22 | pub const TRAIT: Key<ast::TraitDef, TraitId> = Key::new(); | 22 | pub const TRAIT: Key<ast::Trait, TraitId> = Key::new(); |
23 | pub const STRUCT: Key<ast::StructDef, StructId> = Key::new(); | 23 | pub const STRUCT: Key<ast::Struct, StructId> = Key::new(); |
24 | pub const UNION: Key<ast::UnionDef, UnionId> = Key::new(); | 24 | pub const UNION: Key<ast::Union, UnionId> = Key::new(); |
25 | pub const ENUM: Key<ast::EnumDef, EnumId> = Key::new(); | 25 | pub const ENUM: Key<ast::Enum, EnumId> = Key::new(); |
26 | 26 | ||
27 | pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new(); | 27 | pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new(); |
28 | pub const TUPLE_FIELD: Key<ast::TupleFieldDef, FieldId> = Key::new(); | 28 | pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); |
29 | pub const RECORD_FIELD: Key<ast::RecordFieldDef, FieldId> = Key::new(); | 29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); |
30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | 30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); |
31 | 31 | ||
32 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); | 32 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 564434ccc..237b1038a 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -65,6 +65,7 @@ use item_tree::{ | |||
65 | Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, | 65 | Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, |
66 | TypeAlias, Union, | 66 | TypeAlias, Union, |
67 | }; | 67 | }; |
68 | use stdx::impl_from; | ||
68 | 69 | ||
69 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 70 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
70 | pub struct ModuleId { | 71 | pub struct ModuleId { |
@@ -158,17 +159,17 @@ pub struct FunctionId(salsa::InternId); | |||
158 | type FunctionLoc = AssocItemLoc<Function>; | 159 | type FunctionLoc = AssocItemLoc<Function>; |
159 | impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); | 160 | impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); |
160 | 161 | ||
161 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] |
162 | pub struct StructId(salsa::InternId); | 163 | pub struct StructId(salsa::InternId); |
163 | type StructLoc = ItemLoc<Struct>; | 164 | type StructLoc = ItemLoc<Struct>; |
164 | impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); | 165 | impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); |
165 | 166 | ||
166 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 167 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] |
167 | pub struct UnionId(salsa::InternId); | 168 | pub struct UnionId(salsa::InternId); |
168 | pub type UnionLoc = ItemLoc<Union>; | 169 | pub type UnionLoc = ItemLoc<Union>; |
169 | impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); | 170 | impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); |
170 | 171 | ||
171 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 172 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] |
172 | pub struct EnumId(salsa::InternId); | 173 | pub struct EnumId(salsa::InternId); |
173 | pub type EnumLoc = ItemLoc<Enum>; | 174 | pub type EnumLoc = ItemLoc<Enum>; |
174 | impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); | 175 | impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); |
@@ -223,25 +224,6 @@ pub struct TypeParamId { | |||
223 | 224 | ||
224 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; | 225 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; |
225 | 226 | ||
226 | macro_rules! impl_froms { | ||
227 | ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { | ||
228 | $( | ||
229 | impl From<$v> for $e { | ||
230 | fn from(it: $v) -> $e { | ||
231 | $e::$v(it) | ||
232 | } | ||
233 | } | ||
234 | $($( | ||
235 | impl From<$sv> for $e { | ||
236 | fn from(it: $sv) -> $e { | ||
237 | $e::$v($v::$sv(it)) | ||
238 | } | ||
239 | } | ||
240 | )*)? | ||
241 | )* | ||
242 | } | ||
243 | } | ||
244 | |||
245 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 227 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
246 | pub enum ContainerId { | 228 | pub enum ContainerId { |
247 | ModuleId(ModuleId), | 229 | ModuleId(ModuleId), |
@@ -254,16 +236,16 @@ pub enum AssocContainerId { | |||
254 | ImplId(ImplId), | 236 | ImplId(ImplId), |
255 | TraitId(TraitId), | 237 | TraitId(TraitId), |
256 | } | 238 | } |
257 | impl_froms!(AssocContainerId: ContainerId); | 239 | impl_from!(ContainerId for AssocContainerId); |
258 | 240 | ||
259 | /// A Data Type | 241 | /// A Data Type |
260 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 242 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
261 | pub enum AdtId { | 243 | pub enum AdtId { |
262 | StructId(StructId), | 244 | StructId(StructId), |
263 | UnionId(UnionId), | 245 | UnionId(UnionId), |
264 | EnumId(EnumId), | 246 | EnumId(EnumId), |
265 | } | 247 | } |
266 | impl_froms!(AdtId: StructId, UnionId, EnumId); | 248 | impl_from!(StructId, UnionId, EnumId for AdtId); |
267 | 249 | ||
268 | /// The defs which can be visible in the module. | 250 | /// The defs which can be visible in the module. |
269 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 251 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -279,8 +261,8 @@ pub enum ModuleDefId { | |||
279 | TypeAliasId(TypeAliasId), | 261 | TypeAliasId(TypeAliasId), |
280 | BuiltinType(BuiltinType), | 262 | BuiltinType(BuiltinType), |
281 | } | 263 | } |
282 | impl_froms!( | 264 | impl_from!( |
283 | ModuleDefId: ModuleId, | 265 | ModuleId, |
284 | FunctionId, | 266 | FunctionId, |
285 | AdtId(StructId, EnumId, UnionId), | 267 | AdtId(StructId, EnumId, UnionId), |
286 | EnumVariantId, | 268 | EnumVariantId, |
@@ -289,6 +271,7 @@ impl_froms!( | |||
289 | TraitId, | 271 | TraitId, |
290 | TypeAliasId, | 272 | TypeAliasId, |
291 | BuiltinType | 273 | BuiltinType |
274 | for ModuleDefId | ||
292 | ); | 275 | ); |
293 | 276 | ||
294 | /// The defs which have a body. | 277 | /// The defs which have a body. |
@@ -299,7 +282,7 @@ pub enum DefWithBodyId { | |||
299 | ConstId(ConstId), | 282 | ConstId(ConstId), |
300 | } | 283 | } |
301 | 284 | ||
302 | impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); | 285 | impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); |
303 | 286 | ||
304 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 287 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
305 | pub enum AssocItemId { | 288 | pub enum AssocItemId { |
@@ -311,7 +294,7 @@ pub enum AssocItemId { | |||
311 | // sure that you can only turn actual assoc items into AssocItemIds. This would | 294 | // sure that you can only turn actual assoc items into AssocItemIds. This would |
312 | // require not implementing From, and instead having some checked way of | 295 | // require not implementing From, and instead having some checked way of |
313 | // casting them, and somehow making the constructors private, which would be annoying. | 296 | // casting them, and somehow making the constructors private, which would be annoying. |
314 | impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); | 297 | impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId); |
315 | 298 | ||
316 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 299 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] |
317 | pub enum GenericDefId { | 300 | pub enum GenericDefId { |
@@ -326,14 +309,15 @@ pub enum GenericDefId { | |||
326 | // consts can have type parameters from their parents (i.e. associated consts of traits) | 309 | // consts can have type parameters from their parents (i.e. associated consts of traits) |
327 | ConstId(ConstId), | 310 | ConstId(ConstId), |
328 | } | 311 | } |
329 | impl_froms!( | 312 | impl_from!( |
330 | GenericDefId: FunctionId, | 313 | FunctionId, |
331 | AdtId(StructId, EnumId, UnionId), | 314 | AdtId(StructId, EnumId, UnionId), |
332 | TraitId, | 315 | TraitId, |
333 | TypeAliasId, | 316 | TypeAliasId, |
334 | ImplId, | 317 | ImplId, |
335 | EnumVariantId, | 318 | EnumVariantId, |
336 | ConstId | 319 | ConstId |
320 | for GenericDefId | ||
337 | ); | 321 | ); |
338 | 322 | ||
339 | impl From<AssocItemId> for GenericDefId { | 323 | impl From<AssocItemId> for GenericDefId { |
@@ -361,8 +345,8 @@ pub enum AttrDefId { | |||
361 | ImplId(ImplId), | 345 | ImplId(ImplId), |
362 | } | 346 | } |
363 | 347 | ||
364 | impl_froms!( | 348 | impl_from!( |
365 | AttrDefId: ModuleId, | 349 | ModuleId, |
366 | FieldId, | 350 | FieldId, |
367 | AdtId(StructId, EnumId, UnionId), | 351 | AdtId(StructId, EnumId, UnionId), |
368 | EnumVariantId, | 352 | EnumVariantId, |
@@ -373,6 +357,7 @@ impl_froms!( | |||
373 | TypeAliasId, | 357 | TypeAliasId, |
374 | MacroDefId, | 358 | MacroDefId, |
375 | ImplId | 359 | ImplId |
360 | for AttrDefId | ||
376 | ); | 361 | ); |
377 | 362 | ||
378 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 363 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -381,7 +366,7 @@ pub enum VariantId { | |||
381 | StructId(StructId), | 366 | StructId(StructId), |
382 | UnionId(UnionId), | 367 | UnionId(UnionId), |
383 | } | 368 | } |
384 | impl_froms!(VariantId: EnumVariantId, StructId, UnionId); | 369 | impl_from!(EnumVariantId, StructId, UnionId for VariantId); |
385 | 370 | ||
386 | trait Intern { | 371 | trait Intern { |
387 | type ID; | 372 | type ID; |
@@ -536,7 +521,7 @@ impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | |||
536 | } | 521 | } |
537 | } | 522 | } |
538 | 523 | ||
539 | impl AsMacroCall for AstIdWithPath<ast::ModuleItem> { | 524 | impl AsMacroCall for AstIdWithPath<ast::Item> { |
540 | fn as_call_id( | 525 | fn as_call_id( |
541 | &self, | 526 | &self, |
542 | db: &dyn db::DefDatabase, | 527 | db: &dyn db::DefDatabase, |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index b279bdeef..3d9b55a73 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -229,37 +229,37 @@ impl CrateDefMap { | |||
229 | // even), as this should be a great debugging aid. | 229 | // even), as this should be a great debugging aid. |
230 | pub fn dump(&self) -> String { | 230 | pub fn dump(&self) -> String { |
231 | let mut buf = String::new(); | 231 | let mut buf = String::new(); |
232 | go(&mut buf, self, "\ncrate", self.root); | 232 | go(&mut buf, self, "crate", self.root); |
233 | return buf.trim().to_string(); | 233 | return buf; |
234 | 234 | ||
235 | fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { | 235 | fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { |
236 | *buf += path; | 236 | format_to!(buf, "{}\n", path); |
237 | *buf += "\n"; | ||
238 | 237 | ||
239 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); | 238 | let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); |
240 | entries.sort_by_key(|(name, _)| name.clone()); | 239 | entries.sort_by_key(|(name, _)| name.clone()); |
241 | 240 | ||
242 | for (name, def) in entries { | 241 | for (name, def) in entries { |
243 | format_to!(buf, "{}:", name); | 242 | format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string())); |
244 | 243 | ||
245 | if def.types.is_some() { | 244 | if def.types.is_some() { |
246 | *buf += " t"; | 245 | buf.push_str(" t"); |
247 | } | 246 | } |
248 | if def.values.is_some() { | 247 | if def.values.is_some() { |
249 | *buf += " v"; | 248 | buf.push_str(" v"); |
250 | } | 249 | } |
251 | if def.macros.is_some() { | 250 | if def.macros.is_some() { |
252 | *buf += " m"; | 251 | buf.push_str(" m"); |
253 | } | 252 | } |
254 | if def.is_none() { | 253 | if def.is_none() { |
255 | *buf += " _"; | 254 | buf.push_str(" _"); |
256 | } | 255 | } |
257 | 256 | ||
258 | *buf += "\n"; | 257 | buf.push_str("\n"); |
259 | } | 258 | } |
260 | 259 | ||
261 | for (name, child) in map.modules[module].children.iter() { | 260 | for (name, child) in map.modules[module].children.iter() { |
262 | let path = &format!("{}::{}", path, name); | 261 | let path = format!("{}::{}", path, name); |
262 | buf.push('\n'); | ||
263 | go(buf, map, &path, *child); | 263 | go(buf, map, &path, *child); |
264 | } | 264 | } |
265 | } | 265 | } |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index a35ac1024..28b7a20c5 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -36,6 +36,10 @@ use crate::{ | |||
36 | TraitLoc, TypeAliasLoc, UnionLoc, | 36 | TraitLoc, TypeAliasLoc, UnionLoc, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | const GLOB_RECURSION_LIMIT: usize = 100; | ||
40 | const EXPANSION_DEPTH_LIMIT: usize = 128; | ||
41 | const FIXED_POINT_LIMIT: usize = 8192; | ||
42 | |||
39 | pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 43 | pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { |
40 | let crate_graph = db.crate_graph(); | 44 | let crate_graph = db.crate_graph(); |
41 | 45 | ||
@@ -166,7 +170,7 @@ struct MacroDirective { | |||
166 | #[derive(Clone, Debug, Eq, PartialEq)] | 170 | #[derive(Clone, Debug, Eq, PartialEq)] |
167 | struct DeriveDirective { | 171 | struct DeriveDirective { |
168 | module_id: LocalModuleId, | 172 | module_id: LocalModuleId, |
169 | ast_id: AstIdWithPath<ast::ModuleItem>, | 173 | ast_id: AstIdWithPath<ast::Item>, |
170 | } | 174 | } |
171 | 175 | ||
172 | struct DefData<'a> { | 176 | struct DefData<'a> { |
@@ -217,7 +221,7 @@ impl DefCollector<'_> { | |||
217 | ReachedFixedPoint::Yes => break, | 221 | ReachedFixedPoint::Yes => break, |
218 | ReachedFixedPoint::No => i += 1, | 222 | ReachedFixedPoint::No => i += 1, |
219 | } | 223 | } |
220 | if i == 10000 { | 224 | if i == FIXED_POINT_LIMIT { |
221 | log::error!("name resolution is stuck"); | 225 | log::error!("name resolution is stuck"); |
222 | break; | 226 | break; |
223 | } | 227 | } |
@@ -306,7 +310,7 @@ impl DefCollector<'_> { | |||
306 | if export { | 310 | if export { |
307 | self.update( | 311 | self.update( |
308 | self.def_map.root, | 312 | self.def_map.root, |
309 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 313 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
310 | Visibility::Public, | 314 | Visibility::Public, |
311 | ImportType::Named, | 315 | ImportType::Named, |
312 | ); | 316 | ); |
@@ -332,7 +336,7 @@ impl DefCollector<'_> { | |||
332 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | 336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { |
333 | self.update( | 337 | self.update( |
334 | self.def_map.root, | 338 | self.def_map.root, |
335 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 339 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
336 | Visibility::Public, | 340 | Visibility::Public, |
337 | ImportType::Named, | 341 | ImportType::Named, |
338 | ); | 342 | ); |
@@ -530,7 +534,7 @@ impl DefCollector<'_> { | |||
530 | let name = variant_data.name.clone(); | 534 | let name = variant_data.name.clone(); |
531 | let variant = EnumVariantId { parent: e, local_id }; | 535 | let variant = EnumVariantId { parent: e, local_id }; |
532 | let res = PerNs::both(variant.into(), variant.into(), vis); | 536 | let res = PerNs::both(variant.into(), variant.into(), vis); |
533 | (name, res) | 537 | (Some(name), res) |
534 | }) | 538 | }) |
535 | .collect::<Vec<_>>(); | 539 | .collect::<Vec<_>>(); |
536 | self.update(module_id, &resolutions, vis, ImportType::Glob); | 540 | self.update(module_id, &resolutions, vis, ImportType::Glob); |
@@ -546,15 +550,15 @@ impl DefCollector<'_> { | |||
546 | match import.path.segments.last() { | 550 | match import.path.segments.last() { |
547 | Some(last_segment) => { | 551 | Some(last_segment) => { |
548 | let name = match &import.alias { | 552 | let name = match &import.alias { |
549 | Some(ImportAlias::Alias(name)) => name.clone(), | 553 | Some(ImportAlias::Alias(name)) => Some(name.clone()), |
550 | Some(ImportAlias::Underscore) => last_segment.clone(), // FIXME rust-analyzer#2736 | 554 | Some(ImportAlias::Underscore) => None, |
551 | None => last_segment.clone(), | 555 | None => Some(last_segment.clone()), |
552 | }; | 556 | }; |
553 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); | 557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
554 | 558 | ||
555 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | 559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 |
556 | if import.is_extern_crate && module_id == self.def_map.root { | 560 | if import.is_extern_crate && module_id == self.def_map.root { |
557 | if let Some(def) = def.take_types() { | 561 | if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) { |
558 | self.def_map.extern_prelude.insert(name.clone(), def); | 562 | self.def_map.extern_prelude.insert(name.clone(), def); |
559 | } | 563 | } |
560 | } | 564 | } |
@@ -569,36 +573,73 @@ impl DefCollector<'_> { | |||
569 | fn update( | 573 | fn update( |
570 | &mut self, | 574 | &mut self, |
571 | module_id: LocalModuleId, | 575 | module_id: LocalModuleId, |
572 | resolutions: &[(Name, PerNs)], | 576 | resolutions: &[(Option<Name>, PerNs)], |
573 | vis: Visibility, | 577 | vis: Visibility, |
574 | import_type: ImportType, | 578 | import_type: ImportType, |
575 | ) { | 579 | ) { |
580 | self.db.check_canceled(); | ||
576 | self.update_recursive(module_id, resolutions, vis, import_type, 0) | 581 | self.update_recursive(module_id, resolutions, vis, import_type, 0) |
577 | } | 582 | } |
578 | 583 | ||
579 | fn update_recursive( | 584 | fn update_recursive( |
580 | &mut self, | 585 | &mut self, |
581 | module_id: LocalModuleId, | 586 | module_id: LocalModuleId, |
582 | resolutions: &[(Name, PerNs)], | 587 | resolutions: &[(Option<Name>, PerNs)], |
583 | // All resolutions are imported with this visibility; the visibilies in | 588 | // All resolutions are imported with this visibility; the visibilies in |
584 | // the `PerNs` values are ignored and overwritten | 589 | // the `PerNs` values are ignored and overwritten |
585 | vis: Visibility, | 590 | vis: Visibility, |
586 | import_type: ImportType, | 591 | import_type: ImportType, |
587 | depth: usize, | 592 | depth: usize, |
588 | ) { | 593 | ) { |
589 | if depth > 100 { | 594 | if depth > GLOB_RECURSION_LIMIT { |
590 | // prevent stack overflows (but this shouldn't be possible) | 595 | // prevent stack overflows (but this shouldn't be possible) |
591 | panic!("infinite recursion in glob imports!"); | 596 | panic!("infinite recursion in glob imports!"); |
592 | } | 597 | } |
593 | let scope = &mut self.def_map.modules[module_id].scope; | ||
594 | let mut changed = false; | 598 | let mut changed = false; |
599 | |||
595 | for (name, res) in resolutions { | 600 | for (name, res) in resolutions { |
596 | changed |= scope.push_res_with_import( | 601 | match name { |
597 | &mut self.from_glob_import, | 602 | Some(name) => { |
598 | (module_id, name.clone()), | 603 | let scope = &mut self.def_map.modules[module_id].scope; |
599 | res.with_visibility(vis), | 604 | changed |= scope.push_res_with_import( |
600 | import_type, | 605 | &mut self.from_glob_import, |
601 | ); | 606 | (module_id, name.clone()), |
607 | res.with_visibility(vis), | ||
608 | import_type, | ||
609 | ); | ||
610 | } | ||
611 | None => { | ||
612 | let tr = match res.take_types() { | ||
613 | Some(ModuleDefId::TraitId(tr)) => tr, | ||
614 | Some(other) => { | ||
615 | log::debug!("non-trait `_` import of {:?}", other); | ||
616 | continue; | ||
617 | } | ||
618 | None => continue, | ||
619 | }; | ||
620 | let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr); | ||
621 | let should_update = match old_vis { | ||
622 | None => true, | ||
623 | Some(old_vis) => { | ||
624 | let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| { | ||
625 | panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr); | ||
626 | }); | ||
627 | |||
628 | if max_vis == old_vis { | ||
629 | false | ||
630 | } else { | ||
631 | mark::hit!(upgrade_underscore_visibility); | ||
632 | true | ||
633 | } | ||
634 | } | ||
635 | }; | ||
636 | |||
637 | if should_update { | ||
638 | changed = true; | ||
639 | self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis); | ||
640 | } | ||
641 | } | ||
642 | } | ||
602 | } | 643 | } |
603 | 644 | ||
604 | if !changed { | 645 | if !changed { |
@@ -609,14 +650,15 @@ impl DefCollector<'_> { | |||
609 | .get(&module_id) | 650 | .get(&module_id) |
610 | .into_iter() | 651 | .into_iter() |
611 | .flat_map(|v| v.iter()) | 652 | .flat_map(|v| v.iter()) |
653 | .filter(|(glob_importing_module, _)| { | ||
654 | // we know all resolutions have the same visibility (`vis`), so we | ||
655 | // just need to check that once | ||
656 | vis.is_visible_from_def_map(&self.def_map, *glob_importing_module) | ||
657 | }) | ||
612 | .cloned() | 658 | .cloned() |
613 | .collect::<Vec<_>>(); | 659 | .collect::<Vec<_>>(); |
660 | |||
614 | for (glob_importing_module, glob_import_vis) in glob_imports { | 661 | for (glob_importing_module, glob_import_vis) in glob_imports { |
615 | // we know all resolutions have the same visibility (`vis`), so we | ||
616 | // just need to check that once | ||
617 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { | ||
618 | continue; | ||
619 | } | ||
620 | self.update_recursive( | 662 | self.update_recursive( |
621 | glob_importing_module, | 663 | glob_importing_module, |
622 | resolutions, | 664 | resolutions, |
@@ -677,10 +719,6 @@ impl DefCollector<'_> { | |||
677 | self.unexpanded_attribute_macros = attribute_macros; | 719 | self.unexpanded_attribute_macros = attribute_macros; |
678 | 720 | ||
679 | for (module_id, macro_call_id, depth) in resolved { | 721 | for (module_id, macro_call_id, depth) in resolved { |
680 | if depth > 1024 { | ||
681 | log::debug!("Max macro expansion depth reached"); | ||
682 | continue; | ||
683 | } | ||
684 | self.collect_macro_expansion(module_id, macro_call_id, depth); | 722 | self.collect_macro_expansion(module_id, macro_call_id, depth); |
685 | } | 723 | } |
686 | 724 | ||
@@ -717,6 +755,11 @@ impl DefCollector<'_> { | |||
717 | macro_call_id: MacroCallId, | 755 | macro_call_id: MacroCallId, |
718 | depth: usize, | 756 | depth: usize, |
719 | ) { | 757 | ) { |
758 | if depth > EXPANSION_DEPTH_LIMIT { | ||
759 | mark::hit!(macro_expansion_overflow); | ||
760 | log::warn!("macro expansion is too deep"); | ||
761 | return; | ||
762 | } | ||
720 | let file_id: HirFileId = macro_call_id.as_file(); | 763 | let file_id: HirFileId = macro_call_id.as_file(); |
721 | let item_tree = self.db.item_tree(file_id); | 764 | let item_tree = self.db.item_tree(file_id); |
722 | let mod_dir = self.mod_dirs[&module_id].clone(); | 765 | let mod_dir = self.mod_dirs[&module_id].clone(); |
@@ -943,7 +986,7 @@ impl ModCollector<'_, '_> { | |||
943 | .unwrap_or(Visibility::Public); | 986 | .unwrap_or(Visibility::Public); |
944 | self.def_collector.update( | 987 | self.def_collector.update( |
945 | self.module_id, | 988 | self.module_id, |
946 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | 989 | &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], |
947 | vis, | 990 | vis, |
948 | ImportType::Named, | 991 | ImportType::Named, |
949 | ) | 992 | ) |
@@ -1050,14 +1093,14 @@ impl ModCollector<'_, '_> { | |||
1050 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1093 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1051 | self.def_collector.update( | 1094 | self.def_collector.update( |
1052 | self.module_id, | 1095 | self.module_id, |
1053 | &[(name, PerNs::from_def(def, vis, false))], | 1096 | &[(Some(name), PerNs::from_def(def, vis, false))], |
1054 | vis, | 1097 | vis, |
1055 | ImportType::Named, | 1098 | ImportType::Named, |
1056 | ); | 1099 | ); |
1057 | res | 1100 | res |
1058 | } | 1101 | } |
1059 | 1102 | ||
1060 | fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::ModuleItem>) { | 1103 | fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) { |
1061 | for derive_subtree in attrs.by_key("derive").tt_values() { | 1104 | for derive_subtree in attrs.by_key("derive").tt_values() { |
1062 | // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree | 1105 | // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree |
1063 | for tt in &derive_subtree.token_trees { | 1106 | for tt in &derive_subtree.token_trees { |
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs index 39e9a6d97..953961632 100644 --- a/crates/ra_hir_def/src/nameres/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs | |||
@@ -1,23 +1,24 @@ | |||
1 | //! This module resolves `mod foo;` declaration to file. | 1 | //! This module resolves `mod foo;` declaration to file. |
2 | use hir_expand::name::Name; | 2 | use hir_expand::name::Name; |
3 | use ra_db::{FileId, RelativePathBuf}; | 3 | use ra_db::FileId; |
4 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
5 | 5 | ||
6 | use crate::{db::DefDatabase, HirFileId}; | 6 | use crate::{db::DefDatabase, HirFileId}; |
7 | 7 | ||
8 | #[derive(Clone, Debug)] | 8 | #[derive(Clone, Debug)] |
9 | pub(super) struct ModDir { | 9 | pub(super) struct ModDir { |
10 | /// `.` for `mod.rs`, `lib.rs` | 10 | /// `` for `mod.rs`, `lib.rs` |
11 | /// `./foo` for `foo.rs` | 11 | /// `foo/` for `foo.rs` |
12 | /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs` | 12 | /// `foo/bar/` for `mod bar { mod x; }` nested in `foo.rs` |
13 | path: RelativePathBuf, | 13 | /// Invariant: path.is_empty() || path.ends_with('/') |
14 | dir_path: DirPath, | ||
14 | /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/` | 15 | /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/` |
15 | root_non_dir_owner: bool, | 16 | root_non_dir_owner: bool, |
16 | } | 17 | } |
17 | 18 | ||
18 | impl ModDir { | 19 | impl ModDir { |
19 | pub(super) fn root() -> ModDir { | 20 | pub(super) fn root() -> ModDir { |
20 | ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false } | 21 | ModDir { dir_path: DirPath::empty(), root_non_dir_owner: false } |
21 | } | 22 | } |
22 | 23 | ||
23 | pub(super) fn descend_into_definition( | 24 | pub(super) fn descend_into_definition( |
@@ -25,17 +26,21 @@ impl ModDir { | |||
25 | name: &Name, | 26 | name: &Name, |
26 | attr_path: Option<&SmolStr>, | 27 | attr_path: Option<&SmolStr>, |
27 | ) -> ModDir { | 28 | ) -> ModDir { |
28 | let mut path = self.path.clone(); | 29 | let path = match attr_path.map(|it| it.as_str()) { |
29 | match attr_to_path(attr_path) { | 30 | None => { |
30 | None => path.push(&name.to_string()), | 31 | let mut path = self.dir_path.clone(); |
32 | path.push(&name.to_string()); | ||
33 | path | ||
34 | } | ||
31 | Some(attr_path) => { | 35 | Some(attr_path) => { |
32 | if self.root_non_dir_owner { | 36 | let mut path = self.dir_path.join_attr(attr_path, self.root_non_dir_owner); |
33 | assert!(path.pop()); | 37 | if !(path.is_empty() || path.ends_with('/')) { |
38 | path.push('/') | ||
34 | } | 39 | } |
35 | path.push(attr_path); | 40 | DirPath::new(path) |
36 | } | 41 | } |
37 | } | 42 | }; |
38 | ModDir { path, root_non_dir_owner: false } | 43 | ModDir { dir_path: path, root_non_dir_owner: false } |
39 | } | 44 | } |
40 | 45 | ||
41 | pub(super) fn resolve_declaration( | 46 | pub(super) fn resolve_declaration( |
@@ -48,34 +53,87 @@ impl ModDir { | |||
48 | let file_id = file_id.original_file(db.upcast()); | 53 | let file_id = file_id.original_file(db.upcast()); |
49 | 54 | ||
50 | let mut candidate_files = Vec::new(); | 55 | let mut candidate_files = Vec::new(); |
51 | match attr_to_path(attr_path) { | 56 | match attr_path { |
52 | Some(attr_path) => { | 57 | Some(attr_path) => { |
53 | let base = | 58 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) |
54 | if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path }; | ||
55 | candidate_files.push(base.join(attr_path).to_string()) | ||
56 | } | 59 | } |
57 | None => { | 60 | None => { |
58 | candidate_files.push(self.path.join(&format!("{}.rs", name)).to_string()); | 61 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); |
59 | candidate_files.push(self.path.join(&format!("{}/mod.rs", name)).to_string()); | 62 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); |
60 | } | 63 | } |
61 | }; | 64 | }; |
62 | 65 | ||
63 | for candidate in candidate_files.iter() { | 66 | for candidate in candidate_files.it |