diff options
Diffstat (limited to 'crates/ra_hir_def')
31 files changed, 2940 insertions, 2592 deletions
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index 6d43924e3..d96a86b80 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml | |||
@@ -3,6 +3,7 @@ edition = "2018" | |||
3 | name = "ra_hir_def" | 3 | name = "ra_hir_def" |
4 | version = "0.1.0" | 4 | version = "0.1.0" |
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | license = "MIT OR Apache-2.0" | ||
6 | 7 | ||
7 | [lib] | 8 | [lib] |
8 | doctest = false | 9 | doctest = false |
@@ -32,4 +33,4 @@ ra_cfg = { path = "../ra_cfg" } | |||
32 | tt = { path = "../ra_tt", package = "ra_tt" } | 33 | tt = { path = "../ra_tt", package = "ra_tt" } |
33 | 34 | ||
34 | [dev-dependencies] | 35 | [dev-dependencies] |
35 | insta = "0.16.0" | 36 | expect = { path = "../expect" } |
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.iter() { |
64 | if let Some(file_id) = db.resolve_path(file_id, candidate.as_str()) { | 67 | if let Some(file_id) = db.resolve_path(file_id, candidate.as_str()) { |
65 | let mut root_non_dir_owner = false; | ||
66 | let mut mod_path = RelativePathBuf::new(); | ||
67 | let is_mod_rs = candidate.ends_with("mod.rs"); | 68 | let is_mod_rs = candidate.ends_with("mod.rs"); |
68 | if !(is_mod_rs || attr_path.is_some()) { | 69 | |
69 | root_non_dir_owner = true; | 70 | let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() { |
70 | mod_path.push(&name.to_string()); | 71 | (DirPath::empty(), false) |
71 | } | 72 | } else { |
72 | return Ok((file_id, is_mod_rs, ModDir { path: mod_path, root_non_dir_owner })); | 73 | (DirPath::new(format!("{}/", name)), true) |
74 | }; | ||
75 | return Ok((file_id, is_mod_rs, ModDir { dir_path, root_non_dir_owner })); | ||
73 | } | 76 | } |
74 | } | 77 | } |
75 | Err(candidate_files.remove(0)) | 78 | Err(candidate_files.remove(0)) |
76 | } | 79 | } |
77 | } | 80 | } |
78 | 81 | ||
79 | fn attr_to_path(attr: Option<&SmolStr>) -> Option<RelativePathBuf> { | 82 | #[derive(Clone, Debug)] |
80 | attr.and_then(|it| RelativePathBuf::from_path(&it.replace("\\", "/")).ok()) | 83 | struct DirPath(String); |
84 | |||
85 | impl DirPath { | ||
86 | fn assert_invariant(&self) { | ||
87 | assert!(self.0.is_empty() || self.0.ends_with('/')); | ||
88 | } | ||
89 | fn new(repr: String) -> DirPath { | ||
90 | let res = DirPath(repr); | ||
91 | res.assert_invariant(); | ||
92 | res | ||
93 | } | ||
94 | fn empty() -> DirPath { | ||
95 | DirPath::new(String::new()) | ||
96 | } | ||
97 | fn push(&mut self, name: &str) { | ||
98 | self.0.push_str(name); | ||
99 | self.0.push('/'); | ||
100 | self.assert_invariant(); | ||
101 | } | ||
102 | fn parent(&self) -> Option<&str> { | ||
103 | if self.0.is_empty() { | ||
104 | return None; | ||
105 | }; | ||
106 | let idx = | ||
107 | self.0[..self.0.len() - '/'.len_utf8()].rfind('/').map_or(0, |it| it + '/'.len_utf8()); | ||
108 | Some(&self.0[..idx]) | ||
109 | } | ||
110 | /// So this is the case which doesn't really work I think if we try to be | ||
111 | /// 100% platform agnostic: | ||
112 | /// | ||
113 | /// ``` | ||
114 | /// mod a { | ||
115 | /// #[path="C://sad/face"] | ||
116 | /// mod b { mod c; } | ||
117 | /// } | ||
118 | /// ``` | ||
119 | /// | ||
120 | /// Here, we need to join logical dir path to a string path from an | ||
121 | /// attribute. Ideally, we should somehow losslessly communicate the whole | ||
122 | /// construction to `FileLoader`. | ||
123 | fn join_attr(&self, mut attr: &str, relative_to_parent: bool) -> String { | ||
124 | let base = if relative_to_parent { self.parent().unwrap() } else { &self.0 }; | ||
125 | |||
126 | if attr.starts_with("./") { | ||
127 | attr = &attr["./".len()..]; | ||
128 | } | ||
129 | let tmp; | ||
130 | let attr = if attr.contains('\\') { | ||
131 | tmp = attr.replace('\\', "/"); | ||
132 | &tmp | ||
133 | } else { | ||
134 | attr | ||
135 | }; | ||
136 | let res = format!("{}{}", base, attr); | ||
137 | res | ||
138 | } | ||
81 | } | 139 | } |
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 19692e70c..dbfa7fccb 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -226,7 +226,15 @@ impl CrateDefMap { | |||
226 | match enum_data.variant(&segment) { | 226 | match enum_data.variant(&segment) { |
227 | Some(local_id) => { | 227 | Some(local_id) => { |
228 | let variant = EnumVariantId { parent: e, local_id }; | 228 | let variant = EnumVariantId { parent: e, local_id }; |
229 | PerNs::both(variant.into(), variant.into(), Visibility::Public) | 229 | match &*enum_data.variants[local_id].variant_data { |
230 | crate::adt::VariantData::Record(_) => { | ||
231 | PerNs::types(variant.into(), Visibility::Public) | ||
232 | } | ||
233 | crate::adt::VariantData::Tuple(_) | ||
234 | | crate::adt::VariantData::Unit => { | ||
235 | PerNs::both(variant.into(), variant.into(), Visibility::Public) | ||
236 | } | ||
237 | } | ||
230 | } | 238 | } |
231 | None => { | 239 | None => { |
232 | return ResolvePathResult::with( | 240 | return ResolvePathResult::with( |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 503099fb7..839b1de57 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -6,558 +6,531 @@ mod primitives; | |||
6 | 6 | ||
7 | use std::sync::Arc; | 7 | use std::sync::Arc; |
8 | 8 | ||
9 | use insta::assert_snapshot; | 9 | use expect::{expect, Expect}; |
10 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 10 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
11 | use test_utils::mark; | 11 | use test_utils::mark; |
12 | 12 | ||
13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
14 | 14 | ||
15 | fn def_map(ra_fixture: &str) -> String { | ||
16 | compute_crate_def_map(ra_fixture).dump() | ||
17 | } | ||
18 | |||
19 | fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { | 15 | fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { |
20 | let db = TestDB::with_files(fixture); | 16 | let db = TestDB::with_files(fixture); |
21 | let krate = db.crate_graph().iter().next().unwrap(); | 17 | let krate = db.crate_graph().iter().next().unwrap(); |
22 | db.crate_def_map(krate) | 18 | db.crate_def_map(krate) |
23 | } | 19 | } |
24 | 20 | ||
21 | fn check(ra_fixture: &str, expect: Expect) { | ||
22 | let db = TestDB::with_files(ra_fixture); | ||
23 | let krate = db.crate_graph().iter().next().unwrap(); | ||
24 | let actual = db.crate_def_map(krate).dump(); | ||
25 | expect.assert_eq(&actual); | ||
26 | } | ||
27 | |||
25 | #[test] | 28 | #[test] |
26 | fn crate_def_map_smoke_test() { | 29 | fn crate_def_map_smoke_test() { |
27 | let map = def_map( | 30 | check( |
28 | r" | 31 | r#" |
29 | //- /lib.rs | 32 | //- /lib.rs |
30 | mod foo; | 33 | mod foo; |
31 | struct S; | 34 | struct S; |
32 | use crate::foo::bar::E; | 35 | use crate::foo::bar::E; |
33 | use self::E::V; | 36 | use self::E::V; |
34 | |||
35 | //- /foo/mod.rs | ||
36 | pub mod bar; | ||
37 | fn f() {} | ||
38 | |||
39 | //- /foo/bar.rs | ||
40 | pub struct Baz; | ||
41 | |||
42 | union U { | ||
43 | to_be: bool, | ||
44 | not_to_be: u8, | ||
45 | } | ||
46 | 37 | ||
47 | enum E { V } | 38 | //- /foo/mod.rs |
39 | pub mod bar; | ||
40 | fn f() {} | ||
48 | 41 | ||
49 | extern { | 42 | //- /foo/bar.rs |
50 | static EXT: u8; | 43 | pub struct Baz; |
51 | fn ext(); | 44 | |
52 | } | 45 | union U { to_be: bool, not_to_be: u8 } |
53 | ", | 46 | enum E { V } |
47 | |||
48 | extern { | ||
49 | static EXT: u8; | ||
50 | fn ext(); | ||
51 | } | ||
52 | "#, | ||
53 | expect![[r#" | ||
54 | crate | ||
55 | E: t | ||
56 | S: t v | ||
57 | V: t v | ||
58 | foo: t | ||
59 | |||
60 | crate::foo | ||
61 | bar: t | ||
62 | f: v | ||
63 | |||
64 | crate::foo::bar | ||
65 | Baz: t v | ||
66 | E: t | ||
67 | EXT: v | ||
68 | U: t | ||
69 | ext: v | ||
70 | "#]], | ||
54 | ); | 71 | ); |
55 | assert_snapshot!(map, @r###" | ||
56 | â‹®crate | ||
57 | â‹®E: t | ||
58 | â‹®S: t v | ||
59 | â‹®V: t v | ||
60 | â‹®foo: t | ||
61 | â‹® | ||
62 | â‹®crate::foo | ||
63 | â‹®bar: t | ||
64 | â‹®f: v | ||
65 | â‹® | ||
66 | â‹®crate::foo::bar | ||
67 | â‹®Baz: t v | ||
68 | â‹®E: t | ||
69 | â‹®EXT: v | ||
70 | â‹®U: t | ||
71 | â‹®ext: v | ||
72 | "###) | ||
73 | } | 72 | } |
74 | 73 | ||
75 | #[test] | 74 | #[test] |
76 | fn crate_def_map_super_super() { | 75 | fn crate_def_map_super_super() { |
77 | let map = def_map( | 76 | check( |
78 | " | 77 | r#" |
79 | //- /lib.rs | 78 | mod a { |
80 | mod a { | 79 | const A: usize = 0; |
81 | const A: usize = 0; | 80 | mod b { |
82 | 81 | const B: usize = 0; | |
83 | mod b { | 82 | mod c { |
84 | const B: usize = 0; | 83 | use super::super::*; |
85 | |||
86 | mod c { | ||
87 | use super::super::*; | ||
88 | } | ||
89 | } | ||
90 | } | 84 | } |
91 | ", | 85 | } |
86 | } | ||
87 | "#, | ||
88 | expect![[r#" | ||
89 | crate | ||
90 | a: t | ||
91 | |||
92 | crate::a | ||
93 | A: v | ||
94 | b: t | ||
95 | |||
96 | crate::a::b | ||
97 | B: v | ||
98 | c: t | ||
99 | |||
100 | crate::a::b::c | ||
101 | A: v | ||
102 | b: t | ||
103 | "#]], | ||
92 | ); | 104 | ); |
93 | assert_snapshot!(map, @r###" | ||
94 | â‹®crate | ||
95 | â‹®a: t | ||
96 | â‹® | ||
97 | â‹®crate::a | ||
98 | â‹®A: v | ||
99 | â‹®b: t | ||
100 | â‹® | ||
101 | â‹®crate::a::b | ||
102 | â‹®B: v | ||
103 | â‹®c: t | ||
104 | â‹® | ||
105 | â‹®crate::a::b::c | ||
106 | â‹®A: v | ||
107 | â‹®b: t | ||
108 | "###) | ||
109 | } | 105 | } |
110 | 106 | ||
111 | #[test] | 107 | #[test] |
112 | fn crate_def_map_fn_mod_same_name() { | 108 | fn crate_def_map_fn_mod_same_name() { |
113 | let map = def_map( | 109 | check( |
114 | " | 110 | r#" |
115 | //- /lib.rs | 111 | mod m { |
116 | mod m { | 112 | pub mod z {} |
117 | pub mod z {} | 113 | pub fn z() {} |
118 | pub fn z() {} | 114 | } |
119 | } | 115 | "#, |
120 | ", | 116 | expect![[r#" |
117 | crate | ||
118 | m: t | ||
119 | |||
120 | crate::m | ||
121 | z: t v | ||
122 | |||
123 | crate::m::z | ||
124 | "#]], | ||
121 | ); | 125 | ); |
122 | assert_snapshot!(map, @r###" | ||
123 | â‹®crate | ||
124 | â‹®m: t | ||
125 | â‹® | ||
126 | â‹®crate::m | ||
127 | â‹®z: t v | ||
128 | â‹® | ||
129 | â‹®crate::m::z | ||
130 | "###) | ||
131 | } | 126 | } |
132 | 127 | ||
133 | #[test] | 128 | #[test] |
134 | fn bogus_paths() { | 129 | fn bogus_paths() { |
135 | mark::check!(bogus_paths); | 130 | mark::check!(bogus_paths); |
136 | let map = def_map( | 131 | check( |
137 | " | 132 | r#" |
138 | //- /lib.rs | 133 | //- /lib.rs |
139 | mod foo; | 134 | mod foo; |
140 | struct S; | 135 | struct S; |
141 | use self; | 136 | use self; |
142 | 137 | ||
143 | //- /foo/mod.rs | 138 | //- /foo/mod.rs |
144 | use super; | 139 | use super; |
145 | use crate; | 140 | use crate; |
146 | 141 | "#, | |
147 | ", | 142 | expect![[r#" |
143 | crate | ||
144 | S: t v | ||
145 | foo: t | ||
146 | |||
147 | crate::foo | ||
148 | "#]], | ||
148 | ); | 149 | ); |
149 | assert_snapshot!(map, @r###" | ||
150 | â‹®crate | ||
151 | â‹®S: t v | ||
152 | â‹®foo: t | ||
153 | â‹® | ||
154 | â‹®crate::foo | ||
155 | "### | ||
156 | ) | ||
157 | } | 150 | } |
158 | 151 | ||
159 | #[test] | 152 | #[test] |
160 | fn use_as() { | 153 | fn use_as() { |
161 | let map = def_map( | 154 | check( |
162 | " | 155 | r#" |
163 | //- /lib.rs | 156 | //- /lib.rs |
164 | mod foo; | 157 | mod foo; |
165 | 158 | use crate::foo::Baz as Foo; | |
166 | use crate::foo::Baz as Foo; | ||
167 | 159 | ||
168 | //- /foo/mod.rs | 160 | //- /foo/mod.rs |
169 | pub struct Baz; | 161 | pub struct Baz; |
170 | ", | 162 | "#, |
171 | ); | 163 | expect![[r#" |
172 | assert_snapshot!(map, | 164 | crate |
173 | @r###" | 165 | Foo: t v |
174 | â‹®crate | 166 | foo: t |
175 | â‹®Foo: t v | 167 | |
176 | â‹®foo: t | 168 | crate::foo |
177 | â‹® | 169 | Baz: t v |
178 | â‹®crate::foo | 170 | "#]], |
179 | â‹®Baz: t v | ||
180 | "### | ||
181 | ); | 171 | ); |
182 | } | 172 | } |
183 | 173 | ||
184 | #[test] | 174 | #[test] |
185 | fn use_trees() { | 175 | fn use_trees() { |
186 | let map = def_map( | 176 | check( |
187 | " | 177 | r#" |
188 | //- /lib.rs | 178 | //- /lib.rs |
189 | mod foo; | 179 | mod foo; |
190 | 180 | use crate::foo::bar::{Baz, Quux}; | |
191 | use crate::foo::bar::{Baz, Quux}; | ||
192 | 181 | ||
193 | //- /foo/mod.rs | 182 | //- /foo/mod.rs |
194 | pub mod bar; | 183 | pub mod bar; |
195 | 184 | ||
196 | //- /foo/bar.rs | 185 | //- /foo/bar.rs |
197 | pub struct Baz; | 186 | pub struct Baz; |
198 | pub enum Quux {}; | 187 | pub enum Quux {}; |
199 | ", | 188 | "#, |
189 | expect![[r#" | ||
190 | crate | ||
191 | Baz: t v | ||
192 | Quux: t | ||
193 | foo: t | ||
194 | |||
195 | crate::foo | ||
196 | bar: t | ||
197 | |||
198 | crate::foo::bar | ||
199 | Baz: t v | ||
200 | Quux: t | ||
201 | "#]], | ||
200 | ); | 202 | ); |
201 | assert_snapshot!(map, @r###" | ||
202 | â‹®crate | ||
203 | â‹®Baz: t v | ||
204 | â‹®Quux: t | ||
205 | â‹®foo: t | ||
206 | â‹® | ||
207 | â‹®crate::foo | ||
208 | â‹®bar: t | ||
209 | â‹® | ||
210 | â‹®crate::foo::bar | ||
211 | â‹®Baz: t v | ||
212 | â‹®Quux: t | ||
213 | "###); | ||
214 | } | 203 | } |
215 | 204 | ||
216 | #[test] | 205 | #[test] |
217 | fn re_exports() { | 206 | fn re_exports() { |
218 | let map = def_map( | 207 | check( |
219 | " | 208 | r#" |
220 | //- /lib.rs | 209 | //- /lib.rs |
221 | mod foo; | 210 | mod foo; |
222 | 211 | use self::foo::Baz; | |
223 | use self::foo::Baz; | ||
224 | |||
225 | //- /foo/mod.rs | ||
226 | pub mod bar; | ||
227 | 212 | ||
228 | pub use self::bar::Baz; | 213 | //- /foo/mod.rs |
214 | pub mod bar; | ||
215 | pub use self::bar::Baz; | ||
229 | 216 | ||
230 | //- /foo/bar.rs | 217 | //- /foo/bar.rs |
231 | pub struct Baz; | 218 | pub struct Baz; |
232 | ", | 219 | "#, |
220 | expect![[r#" | ||
221 | crate | ||
222 | Baz: t v | ||
223 | foo: t | ||
224 | |||
225 | crate::foo | ||
226 | Baz: t v | ||
227 | bar: t | ||
228 | |||
229 | crate::foo::bar | ||
230 | Baz: t v | ||
231 | "#]], | ||
233 | ); | 232 | ); |
234 | assert_snapshot!(map, @r###" | ||
235 | â‹®crate | ||
236 | â‹®Baz: t v | ||
237 | â‹®foo: t | ||
238 | â‹® | ||
239 | â‹®crate::foo | ||
240 | â‹®Baz: t v | ||
241 | â‹®bar: t | ||
242 | â‹® | ||
243 | â‹®crate::foo::bar | ||
244 | â‹®Baz: t v | ||
245 | "###); | ||
246 | } | 233 | } |
247 | 234 | ||
248 | #[test] | 235 | #[test] |
249 | fn std_prelude() { | 236 | fn std_prelude() { |
250 | mark::check!(std_prelude); | 237 | mark::check!(std_prelude); |
251 | let map = def_map( | 238 | check( |
252 | " | 239 | r#" |
253 | //- /main.rs crate:main deps:test_crate | 240 | //- /main.rs crate:main deps:test_crate |
254 | use Foo::*; | 241 | use Foo::*; |
255 | 242 | ||
256 | //- /lib.rs crate:test_crate | 243 | //- /lib.rs crate:test_crate |
257 | mod prelude; | 244 | mod prelude; |
258 | #[prelude_import] | 245 | #[prelude_import] |
259 | use prelude::*; | 246 | use prelude::*; |
260 | 247 | ||
261 | //- /prelude.rs | 248 | //- /prelude.rs |
262 | pub enum Foo { Bar, Baz }; | 249 | pub enum Foo { Bar, Baz }; |
263 | ", | 250 | "#, |
251 | expect![[r#" | ||
252 | crate | ||
253 | Bar: t v | ||
254 | Baz: t v | ||
255 | "#]], | ||
264 | ); | 256 | ); |
265 | assert_snapshot!(map, @r###" | ||
266 | â‹®crate | ||
267 | â‹®Bar: t v | ||
268 | â‹®Baz: t v | ||
269 | "###); | ||
270 | } | 257 | } |
271 | 258 | ||
272 | #[test] | 259 | #[test] |
273 | fn can_import_enum_variant() { | 260 | fn can_import_enum_variant() { |
274 | mark::check!(can_import_enum_variant); | 261 | mark::check!(can_import_enum_variant); |
275 | let map = def_map( | 262 | check( |
276 | " | 263 | r#" |
277 | //- /lib.rs | 264 | enum E { V } |
278 | enum E { V } | 265 | use self::E::V; |
279 | use self::E::V; | 266 | "#, |
280 | ", | 267 | expect![[r#" |
281 | ); | 268 | crate |
282 | assert_snapshot!(map, @r###" | 269 | E: t |
283 | â‹®crate | 270 | V: t v |
284 | â‹®E: t | 271 | "#]], |
285 | â‹®V: t v | ||
286 | "### | ||
287 | ); | 272 | ); |
288 | } | 273 | } |
289 | 274 | ||
290 | #[test] | 275 | #[test] |
291 | fn edition_2015_imports() { | 276 | fn edition_2015_imports() { |
292 | let map = def_map( | 277 | check( |
293 | " | 278 | r#" |
294 | //- /main.rs crate:main deps:other_crate edition:2015 | 279 | //- /main.rs crate:main deps:other_crate edition:2015 |
295 | mod foo; | 280 | mod foo; |
296 | mod bar; | 281 | mod bar; |
297 | |||
298 | //- /bar.rs | ||
299 | struct Bar; | ||
300 | |||
301 | //- /foo.rs | ||
302 | use bar::Bar; | ||
303 | use other_crate::FromLib; | ||
304 | |||
305 | //- /lib.rs crate:other_crate edition:2018 | ||
306 | struct FromLib; | ||
307 | ", | ||
308 | ); | ||
309 | 282 | ||
310 | assert_snapshot!(map, @r###" | 283 | //- /bar.rs |
311 | â‹®crate | 284 | struct Bar; |
312 | â‹®bar: t | 285 | |
313 | â‹®foo: t | 286 | //- /foo.rs |
314 | â‹® | 287 | use bar::Bar; |
315 | â‹®crate::bar | 288 | use other_crate::FromLib; |
316 | â‹®Bar: t v | 289 | |
317 | â‹® | 290 | //- /lib.rs crate:other_crate edition:2018 |
318 | â‹®crate::foo | 291 | struct FromLib; |
319 | â‹®Bar: t v | 292 | "#, |
320 | â‹®FromLib: t v | 293 | expect![[r#" |
321 | "###); | 294 | crate |
295 | bar: t | ||
296 | foo: t | ||
297 | |||
298 | crate::bar | ||
299 | Bar: t v | ||
300 | |||
301 | crate::foo | ||
302 | Bar: t v | ||
303 | FromLib: t v | ||
304 | "#]], | ||
305 | ); | ||
322 | } | 306 | } |
323 | 307 | ||
324 | #[test] | 308 | #[test] |
325 | fn item_map_using_self() { | 309 | fn item_map_using_self() { |
326 | let map = def_map( | 310 | check( |
327 | " | 311 | r#" |
328 | //- /lib.rs | 312 | //- /lib.rs |
329 | mod foo; | 313 | mod foo; |
330 | use crate::foo::bar::Baz::{self}; | 314 | use crate::foo::bar::Baz::{self}; |
331 | //- /foo/mod.rs | 315 | |
332 | pub mod bar; | 316 | //- /foo/mod.rs |
333 | //- /foo/bar.rs | 317 | pub mod bar; |
334 | pub struct Baz; | 318 | |
335 | ", | 319 | //- /foo/bar.rs |
320 | pub struct Baz; | ||
321 | "#, | ||
322 | expect![[r#" | ||
323 | crate | ||
324 | Baz: t v | ||
325 | foo: t | ||
326 | |||
327 | crate::foo | ||
328 | bar: t | ||
329 | |||
330 | crate::foo::bar | ||
331 | Baz: t v | ||
332 | "#]], | ||
336 | ); | 333 | ); |
337 | assert_snapshot!(map, @r###" | ||
338 | â‹®crate | ||
339 | â‹®Baz: t v | ||
340 | â‹®foo: t | ||
341 | â‹® | ||
342 | â‹®crate::foo | ||
343 | â‹®bar: t | ||
344 | â‹® | ||
345 | â‹®crate::foo::bar | ||
346 | â‹®Baz: t v | ||
347 | "###); | ||
348 | } | 334 | } |
349 | 335 | ||
350 | #[test] | 336 | #[test] |
351 | fn item_map_across_crates() { | 337 | fn item_map_across_crates() { |
352 | let map = def_map( | 338 | check( |
353 | " | 339 | r#" |
354 | //- /main.rs crate:main deps:test_crate | 340 | //- /main.rs crate:main deps:test_crate |
355 | use test_crate::Baz; | 341 | use test_crate::Baz; |
356 | |||
357 | //- /lib.rs crate:test_crate | ||
358 | pub struct Baz; | ||
359 | ", | ||
360 | ); | ||
361 | 342 | ||
362 | assert_snapshot!(map, @r###" | 343 | //- /lib.rs crate:test_crate |
363 | â‹®crate | 344 | pub struct Baz; |
364 | â‹®Baz: t v | 345 | "#, |
365 | "###); | 346 | expect![[r#" |
347 | crate | ||
348 | Baz: t v | ||
349 | "#]], | ||
350 | ); | ||
366 | } | 351 | } |
367 | 352 | ||
368 | #[test] | 353 | #[test] |
369 | fn extern_crate_rename() { | 354 | fn extern_crate_rename() { |
370 | let map = def_map( | 355 | check( |
371 | " | 356 | r#" |
372 | //- /main.rs crate:main deps:alloc | 357 | //- /main.rs crate:main deps:alloc |
373 | extern crate alloc as alloc_crate; | 358 | extern crate alloc as alloc_crate; |
374 | 359 | mod alloc; | |
375 | mod alloc; | 360 | mod sync; |
376 | mod sync; | ||
377 | 361 | ||
378 | //- /sync.rs | 362 | //- /sync.rs |
379 | use alloc_crate::Arc; | 363 | use alloc_crate::Arc; |
380 | 364 | ||
381 | //- /lib.rs crate:alloc | 365 | //- /lib.rs crate:alloc |
382 | struct Arc; | 366 | struct Arc; |
383 | ", | 367 | "#, |
368 | expect![[r#" | ||
369 | crate | ||
370 | alloc_crate: t | ||
371 | sync: t | ||
372 | |||
373 | crate::sync | ||
374 | Arc: t v | ||
375 | "#]], | ||
384 | ); | 376 | ); |
385 | |||
386 | assert_snapshot!(map, @r###" | ||
387 | â‹®crate | ||
388 | â‹®alloc_crate: t | ||
389 | â‹®sync: t | ||
390 | â‹® | ||
391 | â‹®crate::sync | ||
392 | â‹®Arc: t v | ||
393 | "###); | ||
394 | } | 377 | } |
395 | 378 | ||
396 | #[test] | 379 | #[test] |
397 | fn extern_crate_rename_2015_edition() { | 380 | fn extern_crate_rename_2015_edition() { |
398 | let map = def_map( | 381 | check( |
399 | " | 382 | r#" |
400 | //- /main.rs crate:main deps:alloc edition:2015 | 383 | //- /main.rs crate:main deps:alloc edition:2015 |
401 | extern crate alloc as alloc_crate; | 384 | extern crate alloc as alloc_crate; |
402 | 385 | mod alloc; | |
403 | mod alloc; | 386 | mod sync; |
404 | mod sync; | ||
405 | |||
406 | //- /sync.rs | ||
407 | use alloc_crate::Arc; | ||
408 | 387 | ||
409 | //- /lib.rs crate:alloc | 388 | //- /sync.rs |
410 | struct Arc; | 389 | use alloc_crate::Arc; |
411 | ", | ||
412 | ); | ||
413 | 390 | ||
414 | assert_snapshot!(map, | 391 | //- /lib.rs crate:alloc |
415 | @r###" | 392 | struct Arc; |
416 | â‹®crate | 393 | "#, |
417 | â‹®alloc_crate: t | 394 | expect![[r#" |
418 | â‹®sync: t | 395 | crate |
419 | â‹® | 396 | alloc_crate: t |
420 | â‹®crate::sync | 397 | sync: t |
421 | â‹®Arc: t v | 398 | |
422 | "### | 399 | crate::sync |
400 | Arc: t v | ||
401 | "#]], | ||
423 | ); | 402 | ); |
424 | } | 403 | } |
425 | 404 | ||
426 | #[test] | 405 | #[test] |
427 | fn reexport_across_crates() { | 406 | fn reexport_across_crates() { |
428 | let map = def_map( | 407 | check( |
429 | " | 408 | r#" |
430 | //- /main.rs crate:main deps:test_crate | 409 | //- /main.rs crate:main deps:test_crate |
431 | use test_crate::Baz; | 410 | use test_crate::Baz; |
432 | |||
433 | //- /lib.rs crate:test_crate | ||
434 | pub use foo::Baz; | ||
435 | 411 | ||
436 | mod foo; | 412 | //- /lib.rs crate:test_crate |
413 | pub use foo::Baz; | ||
414 | mod foo; | ||
437 | 415 | ||
438 | //- /foo.rs | 416 | //- /foo.rs |
439 | pub struct Baz; | 417 | pub struct Baz; |
440 | ", | 418 | "#, |
419 | expect![[r#" | ||
420 | crate | ||
421 | Baz: t v | ||
422 | "#]], | ||
441 | ); | 423 | ); |
442 | |||
443 | assert_snapshot!(map, @r###" | ||
444 | â‹®crate | ||
445 | â‹®Baz: t v | ||
446 | "###); | ||
447 | } | 424 | } |
448 | 425 | ||
449 | #[test] | 426 | #[test] |
450 | fn values_dont_shadow_extern_crates() { | 427 | fn values_dont_shadow_extern_crates() { |
451 | let map = def_map( | 428 | check( |
452 | " | 429 | r#" |
453 | //- /main.rs crate:main deps:foo | 430 | //- /main.rs crate:main deps:foo |
454 | fn foo() {} | 431 | fn foo() {} |
455 | use foo::Bar; | 432 | use foo::Bar; |
456 | |||
457 | //- /foo/lib.rs crate:foo | ||
458 | pub struct Bar; | ||
459 | ", | ||
460 | ); | ||
461 | 433 | ||
462 | assert_snapshot!(map, @r###" | 434 | //- /foo/lib.rs crate:foo |
463 | â‹®crate | 435 | pub struct Bar; |
464 | â‹®Bar: t v | 436 | "#, |
465 | â‹®foo: v | 437 | expect![[r#" |
466 | "###); | 438 | crate |
439 | Bar: t v | ||
440 | foo: v | ||
441 | "#]], | ||
442 | ); | ||
467 | } | 443 | } |
468 | 444 | ||
469 | #[test] | 445 | #[test] |
470 | fn std_prelude_takes_precedence_above_core_prelude() { | 446 | fn std_prelude_takes_precedence_above_core_prelude() { |
471 | let map = def_map( | 447 | check( |
472 | r#" | 448 | r#" |
473 | //- /main.rs crate:main deps:core,std | 449 | //- /main.rs crate:main deps:core,std |
474 | use {Foo, Bar}; | 450 | use {Foo, Bar}; |
475 | 451 | ||
476 | //- /std.rs crate:std deps:core | 452 | //- /std.rs crate:std deps:core |
477 | #[prelude_import] | 453 | #[prelude_import] |
478 | pub use self::prelude::*; | 454 | pub use self::prelude::*; |
479 | mod prelude { | 455 | mod prelude { |
480 | pub struct Foo; | 456 | pub struct Foo; |
481 | pub use core::prelude::Bar; | 457 | pub use core::prelude::Bar; |
482 | } | 458 | } |
483 | 459 | ||
484 | //- /core.rs crate:core | 460 | //- /core.rs crate:core |
485 | #[prelude_import] | 461 | #[prelude_import] |
486 | pub use self::prelude::*; | 462 | pub use self::prelude::*; |
487 | mod prelude { | 463 | mod prelude { |
488 | pub struct Bar; | 464 | pub struct Bar; |
489 | } | 465 | } |
490 | "#, | 466 | "#, |
467 | expect![[r#" | ||
468 | crate | ||
469 | Bar: t v | ||
470 | Foo: t v | ||
471 | "#]], | ||
491 | ); | 472 | ); |
492 | |||
493 | assert_snapshot!(map, @r###" | ||
494 | â‹®crate | ||
495 | â‹®Bar: t v | ||
496 | â‹®Foo: t v | ||
497 | "###); | ||
498 | } | 473 | } |
499 | 474 | ||
500 | #[test] | 475 | #[test] |
501 | fn cfg_not_test() { | 476 | fn cfg_not_test() { |
502 | let map = def_map( | 477 | check( |
503 | r#" | 478 | r#" |
504 | //- /main.rs crate:main deps:std | 479 | //- /main.rs crate:main deps:std |
505 | use {Foo, Bar, Baz}; | 480 | use {Foo, Bar, Baz}; |
506 | 481 | ||
507 | //- /lib.rs crate:std | 482 | //- /lib.rs crate:std |
508 | #[prelude_import] | 483 | #[prelude_import] |
509 | pub use self::prelude::*; | 484 | pub use self::prelude::*; |
510 | mod prelude { | 485 | mod prelude { |
511 | #[cfg(test)] | 486 | #[cfg(test)] |
512 | pub struct Foo; | 487 | pub struct Foo; |
513 | #[cfg(not(test))] | 488 | #[cfg(not(test))] |
514 | pub struct Bar; | 489 | pub struct Bar; |
515 | #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] | 490 | #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] |
516 | pub struct Baz; | 491 | pub struct Baz; |
517 | } | 492 | } |
518 | "#, | 493 | "#, |
494 | expect![[r#" | ||
495 | crate | ||
496 | Bar: t v | ||
497 | Baz: _ | ||
498 | Foo: _ | ||
499 | "#]], | ||
519 | ); | 500 | ); |
520 | |||
521 | assert_snapshot!(map, @r###" | ||
522 | â‹®crate | ||
523 | â‹®Bar: t v | ||
524 | â‹®Baz: _ | ||
525 | â‹®Foo: _ | ||
526 | "###); | ||
527 | } | 501 | } |
528 | 502 | ||
529 | #[test] | 503 | #[test] |
530 | fn cfg_test() { | 504 | fn cfg_test() { |
531 | let map = def_map( | 505 | check( |
532 | r#" | 506 | r#" |
533 | //- /main.rs crate:main deps:std | 507 | //- /main.rs crate:main deps:std |
534 | use {Foo, Bar, Baz}; | 508 | use {Foo, Bar, Baz}; |
535 | 509 | ||
536 | //- /lib.rs crate:std cfg:test,feature=foo,feature=bar,opt=42 | 510 | //- /lib.rs crate:std cfg:test,feature=foo,feature=bar,opt=42 |
537 | #[prelude_import] | 511 | #[prelude_import] |
538 | pub use self::prelude::*; | 512 | pub use self::prelude::*; |
539 | mod prelude { | 513 | mod prelude { |
540 | #[cfg(test)] | 514 | #[cfg(test)] |
541 | pub struct Foo; | 515 | pub struct Foo; |
542 | #[cfg(not(test))] | 516 | #[cfg(not(test))] |
543 | pub struct Bar; | 517 | pub struct Bar; |
544 | #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] | 518 | #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] |
545 | pub struct Baz; | 519 | pub struct Baz; |
546 | } | 520 | } |
547 | "#, | 521 | "#, |
522 | expect![[r#" | ||
523 | crate | ||
524 | Bar: _ | ||
525 | Baz: t v | ||
526 | Foo: t v | ||
527 | "#]], | ||
548 | ); | 528 | ); |
549 | |||
550 | assert_snapshot!(map, @r###" | ||
551 | â‹®crate | ||
552 | â‹®Bar: _ | ||
553 | â‹®Baz: t v | ||
554 | â‹®Foo: t v | ||
555 | "###); | ||
556 | } | 529 | } |
557 | 530 | ||
558 | #[test] | 531 | #[test] |
559 | fn infer_multiple_namespace() { | 532 | fn infer_multiple_namespace() { |
560 | let map = def_map( | 533 | check( |
561 | r#" | 534 | r#" |
562 | //- /main.rs | 535 | //- /main.rs |
563 | mod a { | 536 | mod a { |
@@ -571,18 +544,147 @@ mod b { | |||
571 | pub const T: () = (); | 544 | pub const T: () = (); |
572 | } | 545 | } |
573 | "#, | 546 | "#, |
547 | expect![[r#" | ||
548 | crate | ||
549 | T: t v | ||
550 | a: t | ||
551 | b: t | ||
552 | |||
553 | crate::b | ||
554 | T: v | ||
555 | |||
556 | crate::a | ||
557 | T: t v | ||
558 | "#]], | ||
559 | ); | ||
560 | } | ||
561 | |||
562 | #[test] | ||
563 | fn underscore_import() { | ||
564 | check( | ||
565 | r#" | ||
566 | //- /main.rs | ||
567 | use tr::Tr as _; | ||
568 | use tr::Tr2 as _; | ||
569 | |||
570 | mod tr { | ||
571 | pub trait Tr {} | ||
572 | pub trait Tr2 {} | ||
573 | } | ||
574 | "#, | ||
575 | expect![[r#" | ||
576 | crate | ||
577 | _: t | ||
578 | _: t | ||
579 | tr: t | ||
580 | |||
581 | crate::tr | ||
582 | Tr: t | ||
583 | Tr2: t | ||
584 | "#]], | ||
585 | ); | ||
586 | } | ||
587 | |||
588 | #[test] | ||
589 | fn underscore_reexport() { | ||
590 | check( | ||
591 | r#" | ||
592 | //- /main.rs | ||
593 | mod tr { | ||
594 | pub trait PubTr {} | ||
595 | pub trait PrivTr {} | ||
596 | } | ||
597 | mod reex { | ||
598 | use crate::tr::PrivTr as _; | ||
599 | pub use crate::tr::PubTr as _; | ||
600 | } | ||
601 | use crate::reex::*; | ||
602 | "#, | ||
603 | expect![[r#" | ||
604 | crate | ||
605 | _: t | ||
606 | reex: t | ||
607 | tr: t | ||
608 | |||
609 | crate::tr | ||
610 | PrivTr: t | ||
611 | PubTr: t | ||
612 | |||
613 | crate::reex | ||
614 | _: t | ||
615 | _: t | ||
616 | "#]], | ||
617 | ); | ||
618 | } | ||
619 | |||
620 | #[test] | ||
621 | fn underscore_pub_crate_reexport() { | ||
622 | mark::check!(upgrade_underscore_visibility); | ||
623 | check( | ||
624 | r#" | ||
625 | //- /main.rs crate:main deps:lib | ||
626 | use lib::*; | ||
627 | |||
628 | //- /lib.rs crate:lib | ||
629 | use tr::Tr as _; | ||
630 | pub use tr::Tr as _; | ||
631 | |||
632 | mod tr { | ||
633 | pub trait Tr {} | ||
634 | } | ||
635 | "#, | ||
636 | expect![[r#" | ||
637 | crate | ||
638 | _: t | ||
639 | "#]], | ||
640 | ); | ||
641 | } | ||
642 | |||
643 | #[test] | ||
644 | fn underscore_nontrait() { | ||
645 | check( | ||
646 | r#" | ||
647 | //- /main.rs | ||
648 | mod m { | ||
649 | pub struct Struct; | ||
650 | pub enum Enum {} | ||
651 | pub const CONST: () = (); | ||
652 | } | ||
653 | use crate::m::{Struct as _, Enum as _, CONST as _}; | ||
654 | "#, | ||
655 | expect![[r#" | ||
656 | crate | ||
657 | m: t | ||
658 | |||
659 | crate::m | ||
660 | CONST: v | ||
661 | Enum: t | ||
662 | Struct: t v | ||
663 | "#]], | ||
574 | ); | 664 | ); |
665 | } | ||
666 | |||
667 | #[test] | ||
668 | fn underscore_name_conflict() { | ||
669 | check( | ||
670 | r#" | ||
671 | //- /main.rs | ||
672 | struct Tr; | ||
673 | |||
674 | use tr::Tr as _; | ||
575 | 675 | ||
576 | assert_snapshot!(map, @r###" | 676 | mod tr { |
577 | â‹®crate | 677 | pub trait Tr {} |
578 | â‹®T: t v | 678 | } |
579 | â‹®a: t | 679 | "#, |
580 | â‹®b: t | 680 | expect![[r#" |
581 | â‹® | 681 | crate |
582 | â‹®crate::b | 682 | _: t |
583 | â‹®T: v | 683 | Tr: t v |
584 | â‹® | 684 | tr: t |
585 | â‹®crate::a | 685 | |
586 | â‹®T: t v | 686 | crate::tr |
587 | "###); | 687 | Tr: t |
688 | "#]], | ||
689 | ); | ||
588 | } | 690 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index 7f3d7509c..2ae836e3c 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs | |||
@@ -2,367 +2,337 @@ use super::*; | |||
2 | 2 | ||
3 | #[test] | 3 | #[test] |
4 | fn glob_1() { | 4 | fn glob_1() { |
5 | let map = def_map( | 5 | check( |
6 | r" | 6 | r#" |
7 | //- /lib.rs | 7 | //- /lib.rs |
8 | mod foo; | 8 | mod foo; |
9 | use foo::*; | 9 | use foo::*; |
10 | 10 | ||
11 | //- /foo/mod.rs | 11 | //- /foo/mod.rs |
12 | pub mod bar; | 12 | pub mod bar; |
13 | pub use self::bar::Baz; | 13 | pub use self::bar::Baz; |
14 | pub struct Foo; | 14 | pub struct Foo; |
15 | 15 | ||
16 | //- /foo/bar.rs | 16 | //- /foo/bar.rs |
17 | pub struct Baz; | 17 | pub struct Baz; |
18 | ", | 18 | "#, |
19 | ); | 19 | expect![[r#" |
20 | assert_snapshot!(map, @r###" | 20 | crate |
21 | â‹®crate | 21 | Baz: t v |
22 | â‹®Baz: t v | 22 | Foo: t v |
23 | â‹®Foo: t v | 23 | bar: t |
24 | â‹®bar: t | 24 | foo: t |
25 | â‹®foo: t | 25 | |
26 | â‹® | 26 | crate::foo |
27 | â‹®crate::foo | 27 | Baz: t v |
28 | â‹®Baz: t v | 28 | Foo: t v |
29 | â‹®Foo: t v | 29 | bar: t |
30 | â‹®bar: t | 30 | |
31 | â‹® | 31 | crate::foo::bar |
32 | â‹®crate::foo::bar | 32 | Baz: t v |
33 | â‹®Baz: t v | 33 | "#]], |
34 | "### | ||
35 | ); | 34 | ); |
36 | } | 35 | } |
37 | 36 | ||
38 | #[test] | 37 | #[test] |
39 | fn glob_2() { | 38 | fn glob_2() { |
40 | let map = def_map( | 39 | check( |
41 | " | 40 | r#" |
42 | //- /lib.rs | 41 | //- /lib.rs |
43 | mod foo; | 42 | mod foo; |
44 | use foo::*; | 43 | use foo::*; |
45 | 44 | ||
46 | //- /foo/mod.rs | 45 | //- /foo/mod.rs |
47 | pub mod bar; | 46 | pub mod bar; |
48 | pub use self::bar::*; | 47 | pub use self::bar::*; |
49 | pub struct Foo; | 48 | pub struct Foo; |
50 | 49 | ||
51 | //- /foo/bar.rs | 50 | //- /foo/bar.rs |
52 | pub struct Baz; | 51 | pub struct Baz; |
53 | pub use super::*; | 52 | pub use super::*; |
54 | ", | 53 | "#, |
55 | ); | 54 | expect![[r#" |
56 | assert_snapshot!(map, @r###" | 55 | crate |
57 | â‹®crate | 56 | Baz: t v |
58 | â‹®Baz: t v | 57 | Foo: t v |
59 | â‹®Foo: t v | 58 | bar: t |
60 | â‹®bar: t | 59 | foo: t |
61 | â‹®foo: t | 60 | |
62 | â‹® | 61 | crate::foo |
63 | â‹®crate::foo | 62 | Baz: t v |
64 | â‹®Baz: t v | 63 | Foo: t v |
65 | â‹®Foo: t v | 64 | bar: t |
66 | â‹®bar: t | 65 | |
67 | â‹® | 66 | crate::foo::bar |
68 | â‹®crate::foo::bar | 67 | Baz: t v |
69 | â‹®Baz: t v | 68 | Foo: t v |
70 | â‹®Foo: t v | 69 | bar: t |
71 | â‹®bar: t | 70 | "#]], |
72 | "### | ||
73 | ); | 71 | ); |
74 | } | 72 | } |
75 | 73 | ||
76 | #[test] | 74 | #[test] |
77 | fn glob_privacy_1() { | 75 | fn glob_privacy_1() { |
78 | let map = def_map( | 76 | check( |
79 | r" | 77 | r" |
80 | //- /lib.rs | 78 | //- /lib.rs |
81 | mod foo; | 79 | mod foo; |
82 | use foo::*; | 80 | use foo::*; |
83 | 81 | ||
84 | //- /foo/mod.rs | 82 | //- /foo/mod.rs |
85 | pub mod bar; | 83 | pub mod bar; |
86 | pub use self::bar::*; | 84 | pub use self::bar::*; |
87 | struct PrivateStructFoo; | 85 | struct PrivateStructFoo; |
88 | 86 | ||
89 | //- /foo/bar.rs | 87 | //- /foo/bar.rs |
90 | pub struct Baz; | 88 | pub struct Baz; |
91 | struct PrivateStructBar; | 89 | struct PrivateStructBar; |
92 | pub use super::*; | 90 | pub use super::*; |
93 | ", | 91 | ", |
94 | ); | 92 | expect![[r#" |
95 | assert_snapshot!(map, @r###" | 93 | crate |
96 | â‹®crate | 94 | Baz: t v |
97 | â‹®Baz: t v | 95 | bar: t |
98 | â‹®bar: t | 96 | foo: t |
99 | â‹®foo: t | 97 | |
100 | â‹® | 98 | crate::foo |
101 | â‹®crate::foo | 99 | Baz: t v |
102 | â‹®Baz: t v | 100 | PrivateStructFoo: t v |
103 | â‹®PrivateStructFoo: t v | 101 | bar: t |
104 | â‹®bar: t | 102 | |
105 | â‹® | 103 | crate::foo::bar |
106 | â‹®crate::foo::bar | 104 | Baz: t v |
107 | â‹®Baz: t v | 105 | PrivateStructBar: t v |
108 | â‹®PrivateStructBar: t v | 106 | PrivateStructFoo: t v |
109 | â‹®PrivateStructFoo: t v | 107 | bar: t |
110 | â‹®bar: t | 108 | "#]], |
111 | "### | ||
112 | ); | 109 | ); |
113 | } | 110 | } |
114 | 111 | ||
115 | #[test] | 112 | #[test] |
116 | fn glob_privacy_2() { | 113 | fn glob_privacy_2() { |
117 | let map = def_map( | 114 | check( |
118 | r" | 115 | r" |
119 | //- /lib.rs | 116 | //- /lib.rs |
120 | mod foo; | 117 | mod foo; |
121 | use foo::*; | 118 | use foo::*; |
122 | use foo::bar::*; | 119 | use foo::bar::*; |
123 | 120 | ||
124 | //- /foo/mod.rs | 121 | //- /foo/mod.rs |
125 | mod bar; | 122 | mod bar; |
126 | fn Foo() {}; | 123 | fn Foo() {}; |
127 | pub struct Foo {}; | 124 | pub struct Foo {}; |
128 | 125 | ||
129 | //- /foo/bar.rs | 126 | //- /foo/bar.rs |
130 | pub(super) struct PrivateBaz; | 127 | pub(super) struct PrivateBaz; |
131 | struct PrivateBar; | 128 | struct PrivateBar; |
132 | pub(crate) struct PubCrateStruct; | 129 | pub(crate) struct PubCrateStruct; |
133 | ", | 130 | ", |
134 | ); | 131 | expect![[r#" |
135 | assert_snapshot!(map, @r###" | 132 | crate |
136 | â‹®crate | 133 | Foo: t |
137 | â‹®Foo: t | 134 | PubCrateStruct: t v |
138 | â‹®PubCrateStruct: t v | 135 | foo: t |
139 | â‹®foo: t | 136 | |
140 | â‹® | 137 | crate::foo |
141 | â‹®crate::foo | 138 | Foo: t v |
142 | â‹®Foo: t v | 139 | bar: t |
143 | â‹®bar: t | 140 | |
144 | â‹® | 141 | crate::foo::bar |
145 | â‹®crate::foo::bar | 142 | PrivateBar: t v |
146 | â‹®PrivateBar: t v | 143 | PrivateBaz: t v |
147 | â‹®PrivateBaz: t v | 144 | PubCrateStruct: t v |
148 | â‹®PubCrateStruct: t v | 145 | "#]], |
149 | "### | ||
150 | ); | 146 | ); |
151 | } | 147 | } |
152 | 148 | ||
153 | #[test] | 149 | #[test] |
154 | fn glob_across_crates() { | 150 | fn glob_across_crates() { |
155 | mark::check!(glob_across_crates); | 151 | mark::check!(glob_across_crates); |
156 | let map = def_map( | 152 | check( |
157 | r" | 153 | r#" |
158 | //- /main.rs crate:main deps:test_crate | 154 | //- /main.rs crate:main deps:test_crate |
159 | use test_crate::*; | 155 | use test_crate::*; |
160 | 156 | ||
161 | //- /lib.rs crate:test_crate | 157 | //- /lib.rs crate:test_crate |
162 | pub struct Baz; | 158 | pub struct Baz; |
163 | ", | 159 | "#, |
164 | ); | 160 | expect![[r#" |
165 | assert_snapshot!(map, @r###" | 161 | crate |
166 | â‹®crate | 162 | Baz: t v |
167 | â‹®Baz: t v | 163 | "#]], |
168 | "### | ||
169 | ); | 164 | ); |
170 | } | 165 | } |
171 | 166 | ||
172 | #[test] | 167 | #[test] |
173 | fn glob_privacy_across_crates() { | 168 | fn glob_privacy_across_crates() { |
174 | let map = def_map( | 169 | check( |
175 | r" | 170 | r#" |
176 | //- /main.rs crate:main deps:test_crate | 171 | //- /main.rs crate:main deps:test_crate |
177 | use test_crate::*; | 172 | use test_crate::*; |
178 | 173 | ||
179 | //- /lib.rs crate:test_crate | 174 | //- /lib.rs crate:test_crate |
180 | pub struct Baz; | 175 | pub struct Baz; |
181 | struct Foo; | 176 | struct Foo; |
182 | ", | 177 | "#, |
183 | ); | 178 | expect![[r#" |
184 | assert_snapshot!(map, @r###" | 179 | crate |
185 | â‹®crate | 180 | Baz: t v |
186 | â‹®Baz: t v | 181 | "#]], |
187 | "### | ||
188 | ); | 182 | ); |
189 | } | 183 | } |
190 | 184 | ||
191 | #[test] | 185 | #[test] |
192 | fn glob_enum() { | 186 | fn glob_enum() { |
193 | mark::check!(glob_enum); | 187 | mark::check!(glob_enum); |
194 | let map = def_map( | 188 | check( |
195 | " | 189 | r#" |
196 | //- /lib.rs | 190 | enum Foo { Bar, Baz } |
197 | enum Foo { | 191 | use self::Foo::*; |
198 | Bar, Baz | 192 | "#, |
199 | } | 193 | expect![[r#" |
200 | use self::Foo::*; | 194 | crate |
201 | ", | 195 | Bar: t v |
202 | ); | 196 | Baz: t v |
203 | assert_snapshot!(map, @r###" | 197 | Foo: t |
204 | â‹®crate | 198 | "#]], |
205 | â‹®Bar: t v | ||
206 | â‹®Baz: t v | ||
207 | â‹®Foo: t | ||
208 | "### | ||
209 | ); | 199 | ); |
210 | } | 200 | } |
211 | 201 | ||
212 | #[test] | 202 | #[test] |
213 | fn glob_enum_group() { | 203 | fn glob_enum_group() { |
214 | mark::check!(glob_enum_group); | 204 | mark::check!(glob_enum_group); |
215 | let map = def_map( | 205 | check( |
216 | r" | 206 | r#" |
217 | //- /lib.rs | 207 | enum Foo { Bar, Baz } |
218 | enum Foo { | 208 | use self::Foo::{*}; |
219 | Bar, Baz | 209 | "#, |
220 | } | 210 | expect![[r#" |
221 | use self::Foo::{*}; | 211 | crate |
222 | ", | 212 | Bar: t v |
223 | ); | 213 | Baz: t v |
224 | assert_snapshot!(map, @r###" | 214 | Foo: t |
225 | â‹®crate | 215 | "#]], |
226 | â‹®Bar: t v | ||
227 | â‹®Baz: t v | ||
228 | â‹®Foo: t | ||
229 | "### | ||
230 | ); | 216 | ); |
231 | } | 217 | } |
232 | 218 | ||
233 | #[test] | 219 | #[test] |
234 | fn glob_shadowed_def() { | 220 | fn glob_shadowed_def() { |
235 | mark::check!(import_shadowed); | 221 | mark::check!(import_shadowed); |
236 | let map = def_map( | 222 | check( |
237 | r###" | 223 | r#" |
238 | //- /lib.rs | 224 | //- /lib.rs |
239 | mod foo; | 225 | mod foo; |
240 | mod bar; | 226 | mod bar; |
241 | 227 | use foo::*; | |
242 | use foo::*; | 228 | use bar::baz; |
243 | use bar::baz; | 229 | use baz::Bar; |
244 | 230 | ||
245 | use baz::Bar; | 231 | //- /foo.rs |
246 | 232 | pub mod baz { pub struct Foo; } | |
247 | //- /foo.rs | 233 | |
248 | pub mod baz { | 234 | //- /bar.rs |
249 | pub struct Foo; | 235 | pub mod baz { pub struct Bar; } |
250 | } | 236 | "#, |
251 | 237 | expect![[r#" | |
252 | //- /bar.rs | 238 | crate |
253 | pub mod baz { | 239 | Bar: t v |
254 | pub struct Bar; | 240 | bar: t |
255 | } | 241 | baz: t |
256 | "###, | 242 | foo: t |
257 | ); | 243 | |
258 | assert_snapshot!(map, @r###" | 244 | crate::bar |
259 | â‹®crate | 245 | baz: t |
260 | â‹®Bar: t v | 246 | |
261 | â‹®bar: t | 247 | crate::bar::baz |
262 | â‹®baz: t | 248 | Bar: t v |
263 | â‹®foo: t | 249 | |
264 | â‹® | 250 | crate::foo |
265 | â‹®crate::bar | 251 | baz: t |
266 | â‹®baz: t | 252 | |
267 | â‹® | 253 | crate::foo::baz |
268 | â‹®crate::bar::baz | 254 | Foo: t v |
269 | â‹®Bar: t v | 255 | "#]], |
270 | â‹® | ||
271 | â‹®crate::foo | ||
272 | â‹®baz: t | ||
273 | â‹® | ||
274 | â‹®crate::foo::baz | ||
275 | â‹®Foo: t v | ||
276 | "### | ||
277 | ); | 256 | ); |
278 | } | 257 | } |
279 | 258 | ||
280 | #[test] | 259 | #[test] |
281 | fn glob_shadowed_def_reversed() { | 260 | fn glob_shadowed_def_reversed() { |
282 | let map = def_map( | 261 | check( |
283 | r###" | 262 | r#" |
284 | //- /lib.rs | 263 | //- /lib.rs |
285 | mod foo; | 264 | mod foo; |
286 | mod bar; | 265 | mod bar; |
287 | 266 | use bar::baz; | |
288 | use bar::baz; | 267 | use foo::*; |
289 | use foo::*; | 268 | use baz::Bar; |
290 | 269 | ||
291 | use baz::Bar; | 270 | //- /foo.rs |
292 | 271 | pub mod baz { pub struct Foo; } | |
293 | //- /foo.rs | 272 | |
294 | pub mod baz { | 273 | //- /bar.rs |
295 | pub struct Foo; | 274 | pub mod baz { pub struct Bar; } |
296 | } | 275 | "#, |
297 | 276 | expect![[r#" | |
298 | //- /bar.rs | 277 | crate |
299 | pub mod baz { | 278 | Bar: t v |
300 | pub struct Bar; | 279 | bar: t |
301 | } | 280 | baz: t |
302 | "###, | 281 | foo: t |
303 | ); | 282 | |
304 | assert_snapshot!(map, @r###" | 283 | crate::bar |
305 | â‹®crate | 284 | baz: t |
306 | â‹®Bar: t v | 285 | |
307 | â‹®bar: t | 286 | crate::bar::baz |
308 | â‹®baz: t | 287 | Bar: t v |
309 | â‹®foo: t | 288 | |
310 | â‹® | 289 | crate::foo |
311 | â‹®crate::bar | 290 | baz: t |
312 | â‹®baz: t | 291 | |
313 | â‹® | 292 | crate::foo::baz |
314 | â‹®crate::bar::baz | 293 | Foo: t v |
315 | â‹®Bar: t v | 294 | "#]], |
316 | â‹® | ||
317 | â‹®crate::foo | ||
318 | â‹®baz: t | ||
319 | â‹® | ||
320 | â‹®crate::foo::baz | ||
321 | â‹®Foo: t v | ||
322 | "### | ||
323 | ); | 295 | ); |
324 | } | 296 | } |
325 | 297 | ||
326 | #[test] | 298 | #[test] |
327 | fn glob_shadowed_def_dependencies() { | 299 | fn glob_shadowed_def_dependencies() { |
328 | let map = def_map( | 300 | check( |
329 | r###" | 301 | r#" |
330 | //- /lib.rs | 302 | mod a { pub mod foo { pub struct X; } } |
331 | mod a { pub mod foo { pub struct X; } } | 303 | mod b { pub use super::a::foo; } |
332 | mod b { pub use super::a::foo; } | 304 | mod c { pub mod foo { pub struct Y; } } |
333 | mod c { pub mod foo { pub struct Y; } } | 305 | mod d { |
334 | mod d { | 306 | use super::c::foo; |
335 | use super::c::foo; | 307 | use super::b::*; |
336 | use super::b::*; | 308 | use foo::Y; |
337 | use foo::Y; | 309 | } |
338 | } | 310 | "#, |
339 | "###, | 311 | expect![[r#" |
340 | ); | 312 | crate |
341 | assert_snapshot!(map, @r###" | 313 | a: t |
342 | â‹®crate | 314 | b: t |
343 | â‹®a: t | 315 | c: t |
344 | â‹®b: t | 316 | d: t |
345 | â‹®c: t | 317 | |
346 | â‹®d: t | 318 | crate::d |
347 | â‹® | 319 | Y: t v |
348 | â‹®crate::d | 320 | foo: t |
349 | â‹®Y: t v | 321 | |
350 | â‹®foo: t | 322 | crate::c |
351 | â‹® | 323 | foo: t |
352 | â‹®crate::c | 324 | |
353 | â‹®foo: t | 325 | crate::c::foo |
354 | â‹® | 326 | Y: t v |
355 | â‹®crate::c::foo | 327 | |
356 | â‹®Y: t v | 328 | crate::b |
357 | â‹® | 329 | foo: t |
358 | â‹®crate::b | 330 | |
359 | â‹®foo: t | 331 | crate::a |
360 | â‹® | 332 | foo: t |
361 | â‹®crate::a | 333 | |
362 | â‹®foo: t | 334 | crate::a::foo |
363 | â‹® | 335 | X: t v |
364 | â‹®crate::a::foo | 336 | "#]], |
365 | â‹®X: t v | ||
366 | "### | ||
367 | ); | 337 | ); |
368 | } | 338 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index 84480d9f6..e0fb8bdef 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs | |||
@@ -2,639 +2,631 @@ use super::*; | |||
2 | 2 | ||
3 | #[test] | 3 | #[test] |
4 | fn macro_rules_are_globally_visible() { | 4 | fn macro_rules_are_globally_visible() { |
5 | let map = def_map( | 5 | check( |
6 | r" | 6 | r#" |
7 | //- /lib.rs | 7 | //- /lib.rs |
8 | macro_rules! structs { | 8 | macro_rules! structs { |
9 | ($($i:ident),*) => { | 9 | ($($i:ident),*) => { |
10 | $(struct $i { field: u32 } )* | 10 | $(struct $i { field: u32 } )* |
11 | } | 11 | } |
12 | } | 12 | } |
13 | structs!(Foo); | 13 | structs!(Foo); |
14 | mod nested; | 14 | mod nested; |
15 | 15 | ||
16 | //- /nested.rs | 16 | //- /nested.rs |
17 | structs!(Bar, Baz); | 17 | structs!(Bar, Baz); |
18 | ", | 18 | "#, |
19 | expect![[r#" | ||
20 | crate | ||
21 | Foo: t | ||
22 | nested: t | ||
23 | |||
24 | crate::nested | ||
25 | Bar: t | ||
26 | Baz: t | ||
27 | "#]], | ||
19 | ); | 28 | ); |
20 | assert_snapshot!(map, @r###" | ||
21 | â‹®crate | ||
22 | â‹®Foo: t | ||
23 | â‹®nested: t | ||
24 | â‹® | ||
25 | â‹®crate::nested | ||
26 | â‹®Bar: t | ||
27 | â‹®Baz: t | ||
28 | "###); | ||
29 | } | 29 | } |
30 | 30 | ||
31 | #[test] | 31 | #[test] |
32 | fn macro_rules_can_define_modules() { | 32 | fn macro_rules_can_define_modules() { |
33 | let map = def_map( | 33 | check( |
34 | r" | 34 | r#" |
35 | //- /lib.rs | 35 | //- /lib.rs |
36 | macro_rules! m { | 36 | macro_rules! m { |
37 | ($name:ident) => { mod $name; } | 37 | ($name:ident) => { mod $name; } |
38 | } | 38 | } |
39 | m!(n1); | 39 | m!(n1); |
40 | 40 | mod m { m!(n3) } | |
41 | mod m { | 41 | |
42 | m!(n3) | 42 | //- /n1.rs |
43 | } | 43 | m!(n2) |
44 | 44 | //- /n1/n2.rs | |
45 | //- /n1.rs | 45 | struct X; |
46 | m!(n2) | 46 | //- /m/n3.rs |
47 | //- /n1/n2.rs | 47 | struct Y; |
48 | struct X; | 48 | "#, |
49 | //- /m/n3.rs | 49 | expect![[r#" |
50 | struct Y; | 50 | crate |
51 | ", | 51 | m: t |
52 | n1: t | ||
53 | |||
54 | crate::m | ||
55 | n3: t | ||
56 | |||
57 | crate::m::n3 | ||
58 | Y: t v | ||
59 | |||
60 | crate::n1 | ||
61 | n2: t | ||
62 | |||
63 | crate::n1::n2 | ||
64 | X: t v | ||
65 | "#]], | ||
52 | ); | 66 | ); |
53 | assert_snapshot!(map, @r###" | ||
54 | â‹®crate | ||
55 | â‹®m: t | ||
56 | â‹®n1: t | ||
57 | â‹® | ||
58 | â‹®crate::m | ||
59 | â‹®n3: t | ||
60 | â‹® | ||
61 | â‹®crate::m::n3 | ||
62 | â‹®Y: t v | ||
63 | â‹® | ||
64 | â‹®crate::n1 | ||
65 | â‹®n2: t | ||
66 | â‹® | ||
67 | â‹®crate::n1::n2 | ||
68 | â‹®X: t v | ||
69 | "###); | ||
70 | } | 67 | } |
71 | 68 | ||
72 | #[test] | 69 | #[test] |
73 | fn macro_rules_from_other_crates_are_visible() { | 70 | fn macro_rules_from_other_crates_are_visible() { |
74 | let map = def_map( | 71 | check( |
75 | " | 72 | r#" |
76 | //- /main.rs crate:main deps:foo | 73 | //- /main.rs crate:main deps:foo |
77 | foo::structs!(Foo, Bar) | 74 | foo::structs!(Foo, Bar) |
78 | mod bar; | 75 | mod bar; |
79 | 76 | ||
80 | //- /bar.rs | 77 | //- /bar.rs |
81 | use crate::*; | 78 | use crate::*; |
82 | 79 | ||
83 | //- /lib.rs crate:foo | 80 | //- /lib.rs crate:foo |
84 | #[macro_export] | 81 | #[macro_export] |
85 | macro_rules! structs { | 82 | macro_rules! structs { |
86 | ($($i:ident),*) => { | 83 | ($($i:ident),*) => { |
87 | $(struct $i { field: u32 } )* | 84 | $(struct $i { field: u32 } )* |
88 | } | 85 | } |
89 | } | 86 | } |
90 | ", | 87 | "#, |
88 | expect![[r#" | ||
89 | crate | ||
90 | Bar: t | ||
91 | Foo: t | ||
92 | bar: t | ||
93 | |||
94 | crate::bar | ||
95 | Bar: t | ||
96 | Foo: t | ||
97 | bar: t | ||
98 | "#]], | ||
91 | ); | 99 | ); |
92 | assert_snapshot!(map, @r###" | ||
93 | â‹®crate | ||
94 | â‹®Bar: t | ||
95 | â‹®Foo: t | ||
96 | â‹®bar: t | ||
97 | â‹® | ||
98 | â‹®crate::bar | ||
99 | â‹®Bar: t | ||
100 | â‹®Foo: t | ||
101 | â‹®bar: t | ||
102 | "###); | ||
103 | } | 100 | } |
104 | 101 | ||
105 | #[test] | 102 | #[test] |
106 | fn macro_rules_export_with_local_inner_macros_are_visible() { | 103 | fn macro_rules_export_with_local_inner_macros_are_visible() { |
107 | let map = def_map( | 104 | check( |
108 | " | 105 | r#" |
109 | //- /main.rs crate:main deps:foo | 106 | //- /main.rs crate:main deps:foo |
110 | foo::structs!(Foo, Bar) | 107 | foo::structs!(Foo, Bar) |
111 | mod bar; | 108 | mod bar; |
112 | 109 | ||
113 | //- /bar.rs | 110 | //- /bar.rs |
114 | use crate::*; | 111 | use crate::*; |
115 | 112 | ||
116 | //- /lib.rs crate:foo | 113 | //- /lib.rs crate:foo |
117 | #[macro_export(local_inner_macros)] | 114 | #[macro_export(local_inner_macros)] |
118 | macro_rules! structs { | 115 | macro_rules! structs { |
119 | ($($i:ident),*) => { | 116 | ($($i:ident),*) => { |
120 | $(struct $i { field: u32 } )* | 117 | $(struct $i { field: u32 } )* |
121 | } | 118 | } |
122 | } | 119 | } |
123 | ", | 120 | "#, |
121 | expect![[r#" | ||
122 | crate | ||
123 | Bar: t | ||
124 | Foo: t | ||
125 | bar: t | ||
126 | |||
127 | crate::bar | ||
128 | Bar: t | ||
129 | Foo: t | ||
130 | bar: t | ||
131 | "#]], | ||
124 | ); | 132 | ); |
125 | assert_snapshot!(map, @r###" | ||
126 | â‹®crate | ||
127 | â‹®Bar: t | ||
128 | â‹®Foo: t | ||
129 | â‹®bar: t | ||
130 | â‹® | ||
131 | â‹®crate::bar | ||
132 | â‹®Bar: t | ||
133 | â‹®Foo: t | ||
134 | â‹®bar: t | ||
135 | "###); | ||
136 | } | 133 | } |
137 | 134 | ||
138 | #[test] | 135 | #[test] |
139 | fn local_inner_macros_makes_local_macros_usable() { | 136 | fn local_inner_macros_makes_local_macros_usable() { |
140 | let map = def_map( | 137 | check( |
141 | " | 138 | r#" |
142 | //- /main.rs crate:main deps:foo | 139 | //- /main.rs crate:main deps:foo |
143 | foo::structs!(Foo, Bar); | 140 | foo::structs!(Foo, Bar); |
144 | mod bar; | 141 | mod bar; |
145 | //- /bar.rs | 142 | |
146 | use crate::*; | 143 | //- /bar.rs |
147 | //- /lib.rs crate:foo | 144 | use crate::*; |
148 | #[macro_export(local_inner_macros)] | 145 | |
149 | macro_rules! structs { | 146 | //- /lib.rs crate:foo |
150 | ($($i:ident),*) => { | 147 | #[macro_export(local_inner_macros)] |
151 | inner!($($i),*); | 148 | macro_rules! structs { |
152 | } | 149 | ($($i:ident),*) => { |
153 | } | 150 | inner!($($i),*); |
154 | #[macro_export] | 151 | } |
155 | macro_rules! inner { | 152 | } |
156 | ($($i:ident),*) => { | 153 | #[macro_export] |
157 | $(struct $i { field: u32 } )* | 154 | macro_rules! inner { |
158 | } | 155 | ($($i:ident),*) => { |
159 | } | 156 | $(struct $i { field: u32 } )* |
160 | ", | 157 | } |
158 | } | ||
159 | "#, | ||
160 | expect![[r#" | ||
161 | crate | ||
162 | Bar: t | ||
163 | Foo: t | ||
164 | bar: t | ||
165 | |||
166 | crate::bar | ||
167 | Bar: t | ||
168 | Foo: t | ||
169 | bar: t | ||
170 | "#]], | ||
161 | ); | 171 | ); |
162 | assert_snapshot!(map, @r###" | ||
163 | â‹®crate | ||
164 | â‹®Bar: t | ||
165 | â‹®Foo: t | ||
166 | â‹®bar: t | ||
167 | â‹® | ||
168 | â‹®crate::bar | ||
169 | â‹®Bar: t | ||
170 | â‹®Foo: t | ||
171 | â‹®bar: t | ||
172 | "###); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | #[test] | 174 | #[test] |
176 | fn unexpanded_macro_should_expand_by_fixedpoint_loop() { | 175 | fn unexpanded_macro_should_expand_by_fixedpoint_loop() { |
177 | let map = def_map( | 176 | check( |
178 | " | 177 | r#" |
179 | //- /main.rs crate:main deps:foo | 178 | //- /main.rs crate:main deps:foo |
180 | macro_rules! baz { | 179 | macro_rules! baz { |
181 | () => { | 180 | () => { |
182 | use foo::bar; | 181 | use foo::bar; |
183 | } | 182 | } |
184 | } | 183 | } |
185 | 184 | foo!(); | |
186 | foo!(); | 185 | bar!(); |
187 | bar!(); | 186 | baz!(); |
188 | baz!(); | 187 | |
189 | 188 | //- /lib.rs crate:foo | |
190 | //- /lib.rs crate:foo | 189 | #[macro_export] |
191 | #[macro_export] | 190 | macro_rules! foo { |
192 | macro_rules! foo { | 191 | () => { |
193 | () => { | 192 | struct Foo { field: u32 } |
194 | struct Foo { field: u32 } | 193 | } |
195 | } | 194 | } |
196 | } | 195 | #[macro_export] |
197 | #[macro_export] | 196 | macro_rules! bar { |
198 | macro_rules! bar { | 197 | () => { |
199 | () => { | 198 | use foo::foo; |
200 | use foo::foo; | 199 | } |
201 | } | 200 | } |
202 | } | 201 | "#, |
203 | ", | 202 | expect![[r#" |
203 | crate | ||
204 | Foo: t | ||
205 | bar: m | ||
206 | foo: m | ||
207 | "#]], | ||
204 | ); | 208 | ); |
205 | assert_snapshot!(map, @r###" | ||
206 | â‹®crate | ||
207 | â‹®Foo: t | ||
208 | â‹®bar: m | ||
209 | â‹®foo: m | ||
210 | "###); | ||
211 | } | 209 | } |
212 | 210 | ||
213 | #[test] | 211 | #[test] |
214 | fn macro_rules_from_other_crates_are_visible_with_macro_use() { | 212 | fn macro_rules_from_other_crates_are_visible_with_macro_use() { |
215 | mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use); | 213 | mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use); |
216 | let map = def_map( | 214 | check( |
217 | " | 215 | r#" |
218 | //- /main.rs crate:main deps:foo | 216 | //- /main.rs crate:main deps:foo |
219 | structs!(Foo); | 217 | structs!(Foo); |
220 | structs_priv!(Bar); | 218 | structs_priv!(Bar); |
221 | structs_not_exported!(MacroNotResolved1); | 219 | structs_not_exported!(MacroNotResolved1); |
222 | crate::structs!(MacroNotResolved2); | 220 | crate::structs!(MacroNotResolved2); |
223 | 221 | ||
224 | mod bar; | 222 | mod bar; |
225 | 223 | ||
226 | #[macro_use] | 224 | #[macro_use] |
227 | extern crate foo; | 225 | extern crate foo; |
228 | 226 | ||
229 | //- /bar.rs | 227 | //- /bar.rs |
230 | structs!(Baz); | 228 | structs!(Baz); |
231 | crate::structs!(MacroNotResolved3); | 229 | crate::structs!(MacroNotResolved3); |
232 | 230 | ||
233 | //- /lib.rs crate:foo | 231 | //- /lib.rs crate:foo |
234 | #[macro_export] | 232 | #[macro_export] |
235 | macro_rules! structs { | 233 | macro_rules! structs { |
236 | ($i:ident) => { struct $i; } | 234 | ($i:ident) => { struct $i; } |
237 | } | 235 | } |
238 | 236 | ||
239 | macro_rules! structs_not_exported { | 237 | macro_rules! structs_not_exported { |
240 | ($i:ident) => { struct $i; } | 238 | ($i:ident) => { struct $i; } |
241 | } | 239 | } |
242 | 240 | ||
243 | mod priv_mod { | 241 | mod priv_mod { |
244 | #[macro_export] | 242 | #[macro_export] |
245 | macro_rules! structs_priv { | 243 | macro_rules! structs_priv { |
246 | ($i:ident) => { struct $i; } | 244 | ($i:ident) => { struct $i; } |
247 | } | 245 | } |
248 | } | 246 | } |
249 | ", | 247 | "#, |
248 | expect![[r#" | ||
249 | crate | ||
250 | Bar: t v | ||
251 | Foo: t v | ||
252 | bar: t | ||
253 | foo: t | ||
254 | |||
255 | crate::bar | ||
256 | Baz: t v | ||
257 | "#]], | ||
250 | ); | 258 | ); |
251 | assert_snapshot!(map, @r###" | ||
252 | â‹®crate | ||
253 | â‹®Bar: t v | ||
254 | â‹®Foo: t v | ||
255 | â‹®bar: t | ||
256 | â‹®foo: t | ||
257 | â‹® | ||
258 | â‹®crate::bar | ||
259 | â‹®Baz: t v | ||
260 | "###); | ||
261 | } | 259 | } |
262 | 260 | ||
263 | #[test] | 261 | #[test] |
264 | fn prelude_is_macro_use() { | 262 | fn prelude_is_macro_use() { |
265 | mark::check!(prelude_is_macro_use); | 263 | mark::check!(prelude_is_macro_use); |
266 | let map = def_map( | 264 | check( |
267 | " | 265 | r#" |
268 | //- /main.rs crate:main deps:foo | 266 | //- /main.rs crate:main deps:foo |
269 | structs!(Foo); | 267 | structs!(Foo); |
270 | structs_priv!(Bar); | 268 | structs_priv!(Bar); |
271 | structs_outside!(Out); | 269 | structs_outside!(Out); |
272 | crate::structs!(MacroNotResolved2); | 270 | crate::structs!(MacroNotResolved2); |
273 | 271 | ||
274 | mod bar; | 272 | mod bar; |
275 | |||
276 | //- /bar.rs | ||
277 | structs!(Baz); | ||
278 | crate::structs!(MacroNotResolved3); | ||
279 | |||
280 | //- /lib.rs crate:foo | ||
281 | #[prelude_import] | ||
282 | use self::prelude::*; | ||
283 | |||
284 | mod prelude { | ||
285 | #[macro_export] | ||
286 | macro_rules! structs { | ||
287 | ($i:ident) => { struct $i; } | ||
288 | } | ||
289 | |||
290 | mod priv_mod { | ||
291 | #[macro_export] | ||
292 | macro_rules! structs_priv { | ||
293 | ($i:ident) => { struct $i; } | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | 273 | ||
274 | //- /bar.rs | ||
275 | structs!(Baz); | ||
276 | crate::structs!(MacroNotResolved3); | ||
277 | |||
278 | //- /lib.rs crate:foo | ||
279 | #[prelude_import] | ||
280 | use self::prelude::*; | ||
281 | |||
282 | mod prelude { | ||
283 | #[macro_export] | ||
284 | macro_rules! structs { | ||
285 | ($i:ident) => { struct $i; } | ||
286 | } | ||
287 | |||
288 | mod priv_mod { | ||
298 | #[macro_export] | 289 | #[macro_export] |
299 | macro_rules! structs_outside { | 290 | macro_rules! structs_priv { |
300 | ($i:ident) => { struct $i; } | 291 | ($i:ident) => { struct $i; } |
301 | } | 292 | } |
302 | ", | 293 | } |
294 | } | ||
295 | |||
296 | #[macro_export] | ||
297 | macro_rules! structs_outside { | ||
298 | ($i:ident) => { struct $i; } | ||
299 | } | ||
300 | "#, | ||
301 | expect![[r#" | ||
302 | crate | ||
303 | Bar: t v | ||
304 | Foo: t v | ||
305 | Out: t v | ||
306 | bar: t | ||
307 | |||
308 | crate::bar | ||
309 | Baz: t v | ||
310 | "#]], | ||
303 | ); | 311 | ); |
304 | assert_snapshot!(map, @r###" | ||
305 | â‹®crate | ||
306 | â‹®Bar: t v | ||
307 | â‹®Foo: t v | ||
308 | â‹®Out: t v | ||
309 | â‹®bar: t | ||
310 | â‹® | ||
311 | â‹®crate::bar | ||
312 | â‹®Baz: t v | ||
313 | "###); | ||
314 | } | 312 | } |
315 | 313 | ||
316 | #[test] | 314 | #[test] |
317 | fn prelude_cycle() { | 315 | fn prelude_cycle() { |
318 | let map = def_map( | 316 | check( |
319 | " | 317 | r#" |
320 | //- /lib.rs | 318 | #[prelude_import] |
321 | #[prelude_import] | 319 | use self::prelude::*; |
322 | use self::prelude::*; | ||
323 | 320 | ||
324 | declare_mod!(); | 321 | declare_mod!(); |
325 | 322 | ||
326 | mod prelude { | 323 | mod prelude { |
327 | macro_rules! declare_mod { | 324 | macro_rules! declare_mod { |
328 | () => (mod foo {}) | 325 | () => (mod foo {}) |
329 | } | 326 | } |
330 | } | 327 | } |
331 | ", | 328 | "#, |
329 | expect![[r#" | ||
330 | crate | ||
331 | prelude: t | ||
332 | |||
333 | crate::prelude | ||
334 | "#]], | ||
332 | ); | 335 | ); |
333 | assert_snapshot!(map, @r###" | ||
334 | â‹®crate | ||
335 | â‹®prelude: t | ||
336 | â‹® | ||
337 | â‹®crate::prelude | ||
338 | "###); | ||
339 | } | 336 | } |
340 | 337 | ||
341 | #[test] | 338 | #[test] |
342 | fn plain_macros_are_legacy_textual_scoped() { | 339 | fn plain_macros_are_legacy_textual_scoped() { |
343 | let map = def_map( | 340 | check( |
344 | r#" | 341 | r#" |
345 | //- /main.rs | 342 | //- /main.rs |
346 | mod m1; | 343 | mod m1; |
347 | bar!(NotFoundNotMacroUse); | 344 | bar!(NotFoundNotMacroUse); |
348 | 345 | ||
349 | mod m2 { | 346 | mod m2 { foo!(NotFoundBeforeInside2); } |
350 | foo!(NotFoundBeforeInside2); | ||
351 | } | ||
352 | 347 | ||
353 | macro_rules! foo { | 348 | macro_rules! foo { |
354 | ($x:ident) => { struct $x; } | 349 | ($x:ident) => { struct $x; } |
355 | } | 350 | } |
356 | foo!(Ok); | 351 | foo!(Ok); |
357 | |||
358 | mod m3; | ||
359 | foo!(OkShadowStop); | ||
360 | bar!(NotFoundMacroUseStop); | ||
361 | |||
362 | #[macro_use] | ||
363 | mod m5 { | ||
364 | #[macro_use] | ||
365 | mod m6 { | ||
366 | macro_rules! foo { | ||
367 | ($x:ident) => { fn $x() {} } | ||
368 | } | ||
369 | } | ||
370 | } | ||
371 | foo!(ok_double_macro_use_shadow); | ||
372 | |||
373 | baz!(NotFoundBefore); | ||
374 | #[macro_use] | ||
375 | mod m7 { | ||
376 | macro_rules! baz { | ||
377 | ($x:ident) => { struct $x; } | ||
378 | } | ||
379 | } | ||
380 | baz!(OkAfter); | ||
381 | 352 | ||
382 | //- /m1.rs | 353 | mod m3; |
383 | foo!(NotFoundBeforeInside1); | 354 | foo!(OkShadowStop); |
384 | macro_rules! bar { | 355 | bar!(NotFoundMacroUseStop); |
385 | ($x:ident) => { struct $x; } | ||
386 | } | ||
387 | 356 | ||
388 | //- /m3/mod.rs | 357 | #[macro_use] |
389 | foo!(OkAfterInside); | 358 | mod m5 { |
359 | #[macro_use] | ||
360 | mod m6 { | ||
390 | macro_rules! foo { | 361 | macro_rules! foo { |
391 | ($x:ident) => { fn $x() {} } | 362 | ($x:ident) => { fn $x() {} } |
392 | } | 363 | } |
393 | foo!(ok_shadow); | 364 | } |
365 | } | ||
366 | foo!(ok_double_macro_use_shadow); | ||
367 | |||
368 | baz!(NotFoundBefore); | ||
369 | #[macro_use] | ||
370 | mod m7 { | ||
371 | macro_rules! baz { | ||
372 | ($x:ident) => { struct $x; } | ||
373 | } | ||
374 | } | ||
375 | baz!(OkAfter); | ||
394 | 376 | ||
395 | #[macro_use] | 377 | //- /m1.rs |
396 | mod m4; | 378 | foo!(NotFoundBeforeInside1); |
397 | bar!(OkMacroUse); | 379 | macro_rules! bar { |
380 | ($x:ident) => { struct $x; } | ||
381 | } | ||
398 | 382 | ||
399 | //- /m3/m4.rs | 383 | //- /m3/mod.rs |
400 | foo!(ok_shadow_deep); | 384 | foo!(OkAfterInside); |
401 | macro_rules! bar { | 385 | macro_rules! foo { |
402 | ($x:ident) => { struct $x; } | 386 | ($x:ident) => { fn $x() {} } |
403 | } | 387 | } |
404 | "#, | 388 | foo!(ok_shadow); |
389 | |||
390 | #[macro_use] | ||
391 | mod m4; | ||
392 | bar!(OkMacroUse); | ||
393 | |||
394 | //- /m3/m4.rs | ||
395 | foo!(ok_shadow_deep); | ||
396 | macro_rules! bar { | ||
397 | ($x:ident) => { struct $x; } | ||
398 | } | ||
399 | "#, | ||
400 | expect![[r#" | ||
401 | crate | ||
402 | Ok: t v | ||
403 | OkAfter: t v | ||
404 | OkShadowStop: t v | ||
405 | m1: t | ||
406 | m2: t | ||
407 | m3: t | ||
408 | m5: t | ||
409 | m7: t | ||
410 | ok_double_macro_use_shadow: v | ||
411 | |||
412 | crate::m7 | ||
413 | |||
414 | crate::m1 | ||
415 | |||
416 | crate::m5 | ||
417 | m6: t | ||
418 | |||
419 | crate::m5::m6 | ||
420 | |||
421 | crate::m2 | ||
422 | |||
423 | crate::m3 | ||
424 | OkAfterInside: t v | ||
425 | OkMacroUse: t v | ||
426 | m4: t | ||
427 | ok_shadow: v | ||
428 | |||
429 | crate::m3::m4 | ||
430 | ok_shadow_deep: v | ||
431 | "#]], | ||
405 | ); | 432 | ); |
406 | assert_snapshot!(map, @r###" | ||
407 | â‹®crate | ||
408 | â‹®Ok: t v | ||
409 | â‹®OkAfter: t v | ||
410 | â‹®OkShadowStop: t v | ||
411 | â‹®m1: t | ||
412 | â‹®m2: t | ||
413 | â‹®m3: t | ||
414 | â‹®m5: t | ||
415 | â‹®m7: t | ||
416 | â‹®ok_double_macro_use_shadow: v | ||
417 | â‹® | ||
418 | â‹®crate::m7 | ||
419 | â‹® | ||
420 | â‹®crate::m1 | ||
421 | â‹® | ||
422 | â‹®crate::m5 | ||
423 | â‹®m6: t | ||
424 | â‹® | ||
425 | â‹®crate::m5::m6 | ||
426 | â‹® | ||
427 | â‹®crate::m2 | ||
428 | â‹® | ||
429 | â‹®crate::m3 | ||
430 | â‹®OkAfterInside: t v | ||
431 | â‹®OkMacroUse: t v | ||
432 | â‹®m4: t | ||
433 | â‹®ok_shadow: v | ||
434 | â‹® | ||
435 | â‹®crate::m3::m4 | ||
436 | â‹®ok_shadow_deep: v | ||
437 | "###); | ||
438 | } | 433 | } |
439 | 434 | ||
440 | #[test] | 435 | #[test] |
441 | fn type_value_macro_live_in_different_scopes() { | 436 | fn type_value_macro_live_in_different_scopes() { |
442 | let map = def_map( | 437 | check( |
443 | " | 438 | r#" |
444 | //- /main.rs | 439 | #[macro_export] |
445 | #[macro_export] | 440 | macro_rules! foo { |
446 | macro_rules! foo { | 441 | ($x:ident) => { type $x = (); } |
447 | ($x:ident) => { type $x = (); } | 442 | } |
448 | } | ||
449 | |||
450 | foo!(foo); | ||
451 | use foo as bar; | ||
452 | 443 | ||
453 | use self::foo as baz; | 444 | foo!(foo); |
454 | fn baz() {} | 445 | use foo as bar; |
455 | ", | 446 | |
447 | use self::foo as baz; | ||
448 | fn baz() {} | ||
449 | "#, | ||
450 | expect![[r#" | ||
451 | crate | ||
452 | bar: t m | ||
453 | baz: t v m | ||
454 | foo: t m | ||
455 | "#]], | ||
456 | ); | 456 | ); |
457 | assert_snapshot!(map, @r###" | ||
458 | â‹®crate | ||
459 | â‹®bar: t m | ||
460 | â‹®baz: t v m | ||
461 | â‹®foo: t m | ||
462 | "###); | ||
463 | } | 457 | } |
464 | 458 | ||
465 | #[test] | 459 | #[test] |
466 | fn macro_use_can_be_aliased() { | 460 | fn macro_use_can_be_aliased() { |
467 | let map = def_map( | 461 | check( |
468 | " | 462 | r#" |
469 | //- /main.rs crate:main deps:foo | 463 | //- /main.rs crate:main deps:foo |
470 | #[macro_use] | 464 | #[macro_use] |
471 | extern crate foo; | 465 | extern crate foo; |
472 | 466 | ||
473 | foo!(Direct); | 467 | foo!(Direct); |
474 | bar!(Alias); | 468 | bar!(Alias); |
475 | 469 | ||
476 | //- /lib.rs crate:foo | 470 | //- /lib.rs crate:foo |
477 | use crate::foo as bar; | 471 | use crate::foo as bar; |
478 | 472 | ||
479 | mod m { | 473 | mod m { |
480 | #[macro_export] | 474 | #[macro_export] |
481 | macro_rules! foo { | 475 | macro_rules! foo { |
482 | ($x:ident) => { struct $x; } | 476 | ($x:ident) => { struct $x; } |
483 | } | 477 | } |
484 | } | 478 | } |
485 | ", | 479 | "#, |
480 | expect![[r#" | ||
481 | crate | ||
482 | Alias: t v | ||
483 | Direct: t v | ||
484 | foo: t | ||
485 | "#]], | ||
486 | ); | 486 | ); |
487 | assert_snapshot!(map, @r###" | ||
488 | â‹®crate | ||
489 | â‹®Alias: t v | ||
490 | â‹®Direct: t v | ||
491 | â‹®foo: t | ||
492 | "###); | ||
493 | } | 487 | } |
494 | 488 | ||
495 | #[test] | 489 | #[test] |
496 | fn path_qualified_macros() { | 490 | fn path_qualified_macros() { |
497 | let map = def_map( | 491 | check( |
498 | " | 492 | r#" |
499 | //- /main.rs | 493 | macro_rules! foo { |
500 | macro_rules! foo { | 494 | ($x:ident) => { struct $x; } |
501 | ($x:ident) => { struct $x; } | 495 | } |
502 | } | ||
503 | 496 | ||
504 | crate::foo!(NotResolved); | 497 | crate::foo!(NotResolved); |
505 | 498 | ||
506 | crate::bar!(OkCrate); | 499 | crate::bar!(OkCrate); |
507 | bar!(OkPlain); | 500 | bar!(OkPlain); |
508 | alias1!(NotHere); | 501 | alias1!(NotHere); |
509 | m::alias1!(OkAliasPlain); | 502 | m::alias1!(OkAliasPlain); |
510 | m::alias2!(OkAliasSuper); | 503 | m::alias2!(OkAliasSuper); |
511 | m::alias3!(OkAliasCrate); | 504 | m::alias3!(OkAliasCrate); |
512 | not_found!(NotFound); | 505 | not_found!(NotFound); |
513 | 506 | ||
514 | mod m { | 507 | mod m { |
515 | #[macro_export] | 508 | #[macro_export] |
516 | macro_rules! bar { | 509 | macro_rules! bar { |
517 | ($x:ident) => { struct $x; } | 510 | ($x:ident) => { struct $x; } |
518 | } | 511 | } |
519 | 512 | pub use bar as alias1; | |
520 | pub use bar as alias1; | 513 | pub use super::bar as alias2; |
521 | pub use super::bar as alias2; | 514 | pub use crate::bar as alias3; |
522 | pub use crate::bar as alias3; | 515 | pub use self::bar as not_found; |
523 | pub use self::bar as not_found; | 516 | } |
524 | } | 517 | "#, |
525 | ", | 518 | expect![[r#" |
519 | crate | ||
520 | OkAliasCrate: t v | ||
521 | OkAliasPlain: t v | ||
522 | OkAliasSuper: t v | ||
523 | OkCrate: t v | ||
524 | OkPlain: t v | ||
525 | bar: m | ||
526 | m: t | ||
527 | |||
528 | crate::m | ||
529 | alias1: m | ||
530 | alias2: m | ||
531 | alias3: m | ||
532 | not_found: _ | ||
533 | "#]], | ||
526 | ); | 534 | ); |
527 | assert_snapshot!(map, @r###" | ||
528 | â‹®crate | ||
529 | â‹®OkAliasCrate: t v | ||
530 | â‹®OkAliasPlain: t v | ||
531 | â‹®OkAliasSuper: t v | ||
532 | â‹®OkCrate: t v | ||
533 | â‹®OkPlain: t v | ||
534 | â‹®bar: m | ||
535 | â‹®m: t | ||
536 | â‹® | ||
537 | â‹®crate::m | ||
538 | â‹®alias1: m | ||
539 | â‹®alias2: m | ||
540 | â‹®alias3: m | ||
541 | â‹®not_found: _ | ||
542 | "###); | ||
543 | } | 535 | } |
544 | 536 | ||
545 | #[test] | 537 | #[test] |
546 | fn macro_dollar_crate_is_correct_in_item() { | 538 | fn macro_dollar_crate_is_correct_in_item() { |
547 | mark::check!(macro_dollar_crate_self); | 539 | mark::check!(macro_dollar_crate_self); |
548 | let map = def_map( | 540 | check( |
549 | " | 541 | r#" |
550 | //- /main.rs crate:main deps:foo | 542 | //- /main.rs crate:main deps:foo |
551 | #[macro_use] | 543 | #[macro_use] |
552 | extern crate foo; | 544 | extern crate foo; |
553 | 545 | ||
554 | #[macro_use] | 546 | #[macro_use] |
555 | mod m { | 547 | mod m { |
556 | macro_rules! current { | 548 | macro_rules! current { |
557 | () => { | 549 | () => { |
558 | use $crate::Foo as FooSelf; | 550 | use $crate::Foo as FooSelf; |
559 | } | ||
560 | } | ||
561 | } | 551 | } |
552 | } | ||
553 | } | ||
562 | 554 | ||
563 | struct Foo; | 555 | struct Foo; |
564 | 556 | ||
565 | current!(); | 557 | current!(); |
566 | not_current1!(); | 558 | not_current1!(); |
567 | foo::not_current2!(); | 559 | foo::not_current2!(); |
568 | |||
569 | //- /lib.rs crate:foo | ||
570 | mod m { | ||
571 | #[macro_export] | ||
572 | macro_rules! not_current1 { | ||
573 | () => { | ||
574 | use $crate::Bar; | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | 560 | ||
579 | #[macro_export] | 561 | //- /lib.rs crate:foo |
580 | macro_rules! not_current2 { | 562 | mod m { |
581 | () => { | 563 | #[macro_export] |
582 | use $crate::Baz; | 564 | macro_rules! not_current1 { |
583 | } | 565 | () => { |
566 | use $crate::Bar; | ||
584 | } | 567 | } |
568 | } | ||
569 | } | ||
585 | 570 | ||
586 | struct Bar; | 571 | #[macro_export] |
587 | struct Baz; | 572 | macro_rules! not_current2 { |
588 | ", | 573 | () => { |
574 | use $crate::Baz; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | struct Bar; | ||
579 | struct Baz; | ||
580 | "#, | ||
581 | expect![[r#" | ||
582 | crate | ||
583 | Bar: t v | ||
584 | Baz: t v | ||
585 | Foo: t v | ||
586 | FooSelf: t v | ||
587 | foo: t | ||
588 | m: t | ||
589 | |||
590 | crate::m | ||
591 | "#]], | ||
589 | ); | 592 | ); |
590 | assert_snapshot!(map, @r###" | ||
591 | â‹®crate | ||
592 | â‹®Bar: t v | ||
593 | â‹®Baz: t v | ||
594 | â‹®Foo: t v | ||
595 | â‹®FooSelf: t v | ||
596 | â‹®foo: t | ||
597 | â‹®m: t | ||
598 | â‹® | ||
599 | â‹®crate::m | ||
600 | "###); | ||
601 | } | 593 | } |
602 | 594 | ||
603 | #[test] | 595 | #[test] |
604 | fn macro_dollar_crate_is_correct_in_indirect_deps() { | 596 | fn macro_dollar_crate_is_correct_in_indirect_deps() { |
605 | mark::check!(macro_dollar_crate_other); | 597 | mark::check!(macro_dollar_crate_other); |
606 | // From std | 598 | // From std |
607 | let map = def_map( | 599 | check( |
608 | r#" | 600 | r#" |
609 | //- /main.rs crate:main deps:std | 601 | //- /main.rs crate:main deps:std |
610 | foo!(); | 602 | foo!(); |
611 | 603 | ||
612 | //- /std.rs crate:std deps:core | 604 | //- /std.rs crate:std deps:core |
613 | #[prelude_import] | 605 | #[prelude_import] |
614 | use self::prelude::*; | 606 | use self::prelude::*; |
615 | 607 | ||
616 | pub use core::foo; | 608 | pub use core::foo; |
617 | 609 | ||
618 | mod prelude {} | 610 | mod prelude {} |
619 | 611 | ||
620 | #[macro_use] | 612 | #[macro_use] |
621 | mod std_macros; | 613 | mod std_macros; |
622 | 614 | ||
623 | //- /core.rs crate:core | 615 | //- /core.rs crate:core |
624 | #[macro_export] | 616 | #[macro_export] |
625 | macro_rules! foo { | 617 | macro_rules! foo { |
626 | () => { | 618 | () => { |
627 | use $crate::bar; | 619 | use $crate::bar; |
628 | } | 620 | } |
629 | } | 621 | } |
630 | 622 | ||
631 | pub struct bar; | 623 | pub struct bar; |
632 | "#, | 624 | "#, |
625 | expect![[r#" | ||
626 | crate | ||
627 | bar: t v | ||
628 | "#]], | ||
633 | ); | 629 | ); |
634 | assert_snapshot!(map, @r###" | ||
635 | â‹®crate | ||
636 | â‹®bar: t v | ||
637 | "###); | ||
638 | } | 630 | } |
639 | 631 | ||
640 | #[test] | 632 | #[test] |
@@ -642,21 +634,36 @@ fn expand_derive() { | |||
642 | let map = compute_crate_def_map( | 634 | let map = compute_crate_def_map( |
643 | " | 635 | " |
644 | //- /main.rs | 636 | //- /main.rs |
645 | #[derive(Clone)] | 637 | #[derive(Copy, Clone)] |
646 | struct Foo; | 638 | struct Foo; |
647 | ", | 639 | ", |
648 | ); | 640 | ); |
649 | assert_eq!(map.modules[map.root].scope.impls().len(), 1); | 641 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); |
650 | } | 642 | } |
651 | 643 | ||
652 | #[test] | 644 | #[test] |
653 | fn expand_multiple_derive() { | 645 | fn macro_expansion_overflow() { |
654 | let map = compute_crate_def_map( | 646 | mark::check!(macro_expansion_overflow); |
655 | " | 647 | check( |
656 | //- /main.rs | 648 | r#" |
657 | #[derive(Copy, Clone)] | 649 | macro_rules! a { |
658 | struct Foo; | 650 | ($e:expr; $($t:tt)*) => { |
659 | ", | 651 | b!($($t)*); |
652 | }; | ||
653 | () => {}; | ||
654 | } | ||
655 | |||
656 | macro_rules! b { | ||
657 | (static = $e:expr; $($t:tt)*) => { | ||
658 | a!($e; $($t)*); | ||
659 | }; | ||
660 | () => {}; | ||
661 | } | ||
662 | |||
663 | b! { static = #[] (); } | ||
664 | "#, | ||
665 | expect![[r#" | ||
666 | crate | ||
667 | "#]], | ||
660 | ); | 668 | ); |
661 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); | ||
662 | } | 669 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index 753684201..ae58948c4 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -3,710 +3,672 @@ use super::*; | |||
3 | #[test] | 3 | #[test] |
4 | fn name_res_works_for_broken_modules() { | 4 | fn name_res_works_for_broken_modules() { |
5 | mark::check!(name_res_works_for_broken_modules); | 5 | mark::check!(name_res_works_for_broken_modules); |
6 | let map = def_map( | 6 | check( |
7 | r" | 7 | r" |
8 | //- /lib.rs | 8 | //- /lib.rs |
9 | mod foo // no `;`, no body | 9 | mod foo // no `;`, no body |
10 | 10 | use self::foo::Baz; | |
11 | use self::foo::Baz; | 11 | |
12 | 12 | //- /foo/mod.rs | |
13 | //- /foo/mod.rs | 13 | pub mod bar; |
14 | pub mod bar; | 14 | pub use self::bar::Baz; |
15 | 15 | ||
16 | pub use self::bar::Baz; | 16 | //- /foo/bar.rs |
17 | 17 | pub struct Baz; | |
18 | //- /foo/bar.rs | 18 | ", |
19 | pub struct Baz; | 19 | expect![[r#" |
20 | ", | 20 | crate |
21 | Baz: _ | ||
22 | foo: t | ||
23 | |||
24 | crate::foo | ||
25 | "#]], | ||
21 | ); | 26 | ); |
22 | assert_snapshot!(map, @r###" | ||
23 | crate | ||
24 | Baz: _ | ||
25 | foo: t | ||
26 | |||
27 | crate::foo | ||
28 | "###); | ||
29 | } | 27 | } |
30 | 28 | ||
31 | #[test] | 29 | #[test] |
32 | fn nested_module_resolution() { | 30 | fn nested_module_resolution() { |
33 | let map = def_map( | 31 | check( |
34 | r" | 32 | r#" |
35 | //- /lib.rs | 33 | //- /lib.rs |
36 | mod n1; | 34 | mod n1; |
37 | 35 | ||
38 | //- /n1.rs | 36 | //- /n1.rs |
39 | mod n2; | 37 | mod n2; |
40 | 38 | ||
41 | //- /n1/n2.rs | 39 | //- /n1/n2.rs |
42 | struct X; | 40 | struct X; |
43 | ", | 41 | "#, |
42 | expect![[r#" | ||
43 | crate | ||
44 | n1: t | ||
45 | |||
46 | crate::n1 | ||
47 | n2: t | ||
48 | |||
49 | crate::n1::n2 | ||
50 | X: t v | ||
51 | "#]], | ||
44 | ); | 52 | ); |
45 | |||
46 | assert_snapshot!(map, @r###" | ||
47 | â‹®crate | ||
48 | â‹®n1: t | ||
49 | â‹® | ||
50 | â‹®crate::n1 | ||
51 | â‹®n2: t | ||
52 | â‹® | ||
53 | â‹®crate::n1::n2 | ||
54 | â‹®X: t v | ||
55 | "###); | ||
56 | } | 53 | } |
57 | 54 | ||
58 | #[test] | 55 | #[test] |
59 | fn nested_module_resolution_2() { | 56 | fn nested_module_resolution_2() { |
60 | let map = def_map( | 57 | check( |
61 | r" | 58 | r#" |
62 | //- /lib.rs | 59 | //- /lib.rs |
63 | mod prelude; | 60 | mod prelude; |
64 | mod iter; | 61 | mod iter; |
65 | 62 | ||
66 | //- /prelude.rs | 63 | //- /prelude.rs |
67 | pub use crate::iter::Iterator; | 64 | pub use crate::iter::Iterator; |
68 | 65 | ||
69 | //- /iter.rs | 66 | //- /iter.rs |
70 | pub use self::traits::Iterator; | 67 | pub use self::traits::Iterator; |
71 | mod traits; | 68 | mod traits; |
72 | 69 | ||
73 | //- /iter/traits.rs | 70 | //- /iter/traits.rs |
74 | pub use self::iterator::Iterator; | 71 | pub use self::iterator::Iterator; |
75 | mod iterator; | 72 | mod iterator; |
76 | 73 | ||
77 | //- /iter/traits/iterator.rs | 74 | //- /iter/traits/iterator.rs |
78 | pub trait Iterator; | 75 | pub trait Iterator; |
79 | ", | 76 | "#, |
77 | expect![[r#" | ||
78 | crate | ||
79 | iter: t | ||
80 | prelude: t | ||
81 | |||
82 | crate::iter | ||
83 | Iterator: t | ||
84 | traits: t | ||
85 | |||
86 | crate::iter::traits | ||
87 | Iterator: t | ||
88 | iterator: t | ||
89 | |||
90 | crate::iter::traits::iterator | ||
91 | Iterator: t | ||
92 | |||
93 | crate::prelude | ||
94 | Iterator: t | ||
95 | "#]], | ||
80 | ); | 96 | ); |
81 | |||
82 | assert_snapshot!(map, @r###" | ||
83 | â‹®crate | ||
84 | â‹®iter: t | ||
85 | â‹®prelude: t | ||
86 | â‹® | ||
87 | â‹®crate::iter | ||
88 | â‹®Iterator: t | ||
89 | â‹®traits: t | ||
90 | â‹® | ||
91 | â‹®crate::iter::traits | ||
92 | â‹®Iterator: t | ||
93 | â‹®iterator: t | ||
94 | â‹® | ||
95 | â‹®crate::iter::traits::iterator | ||
96 | â‹®Iterator: t | ||
97 | â‹® | ||
98 | â‹®crate::prelude | ||
99 | â‹®Iterator: t | ||
100 | "###); | ||
101 | } | 97 | } |
102 | 98 | ||
103 | #[test] | 99 | #[test] |
104 | fn module_resolution_works_for_non_standard_filenames() { | 100 | fn module_resolution_works_for_non_standard_filenames() { |
105 | let map = def_map( | 101 | check( |
106 | " | 102 | r#" |
107 | //- /my_library.rs crate:my_library | 103 | //- /my_library.rs crate:my_library |
108 | mod foo; | 104 | mod foo; |
109 | use self::foo::Bar; | 105 | use self::foo::Bar; |
110 | 106 | ||
111 | //- /foo/mod.rs | 107 | //- /foo/mod.rs |
112 | pub struct Bar; | 108 | pub struct Bar; |
113 | ", | 109 | "#, |
110 | expect![[r#" | ||
111 | crate | ||
112 | Bar: t v | ||
113 | foo: t | ||
114 | |||
115 | crate::foo | ||
116 | Bar: t v | ||
117 | "#]], | ||
114 | ); | 118 | ); |
115 | |||
116 | assert_snapshot!(map, @r###" | ||
117 | â‹®crate | ||
118 | â‹®Bar: t v | ||
119 | â‹®foo: t | ||
120 | â‹® | ||
121 | â‹®crate::foo | ||
122 | â‹®Bar: t v | ||
123 | "###); | ||
124 | } | 119 | } |
125 | 120 | ||
126 | #[test] | 121 | #[test] |
127 | fn module_resolution_works_for_raw_modules() { | 122 | fn module_resolution_works_for_raw_modules() { |
128 | let map = def_map( | 123 | check( |
129 | " | 124 | r#" |
130 | //- /lib.rs | 125 | //- /lib.rs |
131 | mod r#async; | 126 | mod r#async; |
132 | use self::r#async::Bar; | 127 | use self::r#async::Bar; |
133 | 128 | ||
134 | //- /async.rs | 129 | //- /async.rs |
135 | pub struct Bar; | 130 | pub struct Bar; |
136 | ", | 131 | "#, |
132 | expect![[r#" | ||
133 | crate | ||
134 | Bar: t v | ||
135 | async: t | ||
136 | |||
137 | crate::async | ||
138 | Bar: t v | ||
139 | "#]], | ||
137 | ); | 140 | ); |
138 | |||
139 | assert_snapshot!(map, @r###" | ||
140 | â‹®crate | ||
141 | â‹®Bar: t v | ||
142 | â‹®async: t | ||
143 | â‹® | ||
144 | â‹®crate::async | ||
145 | â‹®Bar: t v | ||
146 | "###); | ||
147 | } | 141 | } |
148 | 142 | ||
149 | #[test] | 143 | #[test] |
150 | fn module_resolution_decl_path() { | 144 | fn module_resolution_decl_path() { |
151 | let map = def_map( | 145 | check( |
152 | r###" | 146 | r#" |
153 | //- /lib.rs | 147 | //- /lib.rs |
154 | #[path = "bar/baz/foo.rs"] | 148 | #[path = "bar/baz/foo.rs"] |
155 | mod foo; | 149 | mod foo; |
156 | use self::foo::Bar; | 150 | use self::foo::Bar; |
157 | 151 | ||
158 | //- /bar/baz/foo.rs | 152 | //- /bar/baz/foo.rs |
159 | pub struct Bar; | 153 | pub struct Bar; |
160 | "###, | 154 | "#, |
155 | expect![[r#" | ||
156 | crate | ||
157 | Bar: t v | ||
158 | foo: t | ||
159 | |||
160 | crate::foo | ||
161 | Bar: t v | ||
162 | "#]], | ||
161 | ); | 163 | ); |
162 | |||
163 | assert_snapshot!(map, @r###" | ||
164 | â‹®crate | ||
165 | â‹®Bar: t v | ||
166 | â‹®foo: t | ||
167 | â‹® | ||
168 | â‹®crate::foo | ||
169 | â‹®Bar: t v | ||
170 | "###); | ||
171 | } | 164 | } |
172 | 165 | ||
173 | #[test] | 166 | #[test] |
174 | fn module_resolution_module_with_path_in_mod_rs() { | 167 | fn module_resolution_module_with_path_in_mod_rs() { |
175 | let map = def_map( | 168 | check( |
176 | r###" | 169 | r#" |
177 | //- /main.rs | 170 | //- /main.rs |
178 | mod foo; | 171 | mod foo; |
179 | 172 | ||
180 | //- /foo/mod.rs | 173 | //- /foo/mod.rs |
181 | #[path = "baz.rs"] | 174 | #[path = "baz.rs"] |
182 | pub mod bar; | 175 | pub mod bar; |
183 | 176 | use self::bar::Baz; | |
184 | use self::bar::Baz; | 177 | |
185 | 178 | //- /foo/baz.rs | |
186 | //- /foo/baz.rs | 179 | pub struct Baz; |
187 | pub struct Baz; | 180 | "#, |
188 | "###, | 181 | expect![[r#" |
182 | crate | ||
183 | foo: t | ||
184 | |||
185 | crate::foo | ||
186 | Baz: t v | ||
187 | bar: t | ||
188 | |||
189 | crate::foo::bar | ||
190 | Baz: t v | ||
191 | "#]], | ||
189 | ); | 192 | ); |
190 | |||
191 | assert_snapshot!(map, @r###" | ||
192 | â‹®crate | ||
193 | â‹®foo: t | ||
194 | â‹® | ||
195 | â‹®crate::foo | ||
196 | â‹®Baz: t v | ||
197 | â‹®bar: t | ||
198 | â‹® | ||
199 | â‹®crate::foo::bar | ||
200 | â‹®Baz: t v | ||
201 | "###); | ||
202 | } | 193 | } |
203 | 194 | ||
204 | #[test] | 195 | #[test] |
205 | fn module_resolution_module_with_path_non_crate_root() { | 196 | fn module_resolution_module_with_path_non_crate_root() { |
206 | let map = def_map( | 197 | check( |
207 | r###" | 198 | r#" |
208 | //- /main.rs | 199 | //- /main.rs |
209 | mod foo; | 200 | mod foo; |
210 | 201 | ||
211 | //- /foo.rs | 202 | //- /foo.rs |
212 | #[path = "baz.rs"] | 203 | #[path = "baz.rs"] |
213 | pub mod bar; | 204 | pub mod bar; |
214 | 205 | use self::bar::Baz; | |
215 | use self::bar::Baz; | 206 | |
216 | 207 | //- /baz.rs | |
217 | //- /baz.rs | 208 | pub struct Baz; |
218 | pub struct Baz; | 209 | "#, |
219 | "###, | 210 | expect![[r#" |
211 | crate | ||
212 | foo: t | ||
213 | |||
214 | crate::foo | ||
215 | Baz: t v | ||
216 | bar: t | ||
217 | |||
218 | crate::foo::bar | ||
219 | Baz: t v | ||
220 | "#]], | ||
220 | ); | 221 | ); |
221 | |||
222 | assert_snapshot!(map, @r###" | ||
223 | â‹®crate | ||
224 | â‹®foo: t | ||
225 | â‹® | ||
226 | â‹®crate::foo | ||
227 | â‹®Baz: t v | ||
228 | â‹®bar: t | ||
229 | â‹® | ||
230 | â‹®crate::foo::bar | ||
231 | â‹®Baz: t v | ||
232 | "###); | ||
233 | } | 222 | } |
234 | 223 | ||
235 | #[test] | 224 | #[test] |
236 | fn module_resolution_module_decl_path_super() { | 225 | fn module_resolution_module_decl_path_super() { |
237 | let map = def_map( | 226 | check( |
238 | r###" | 227 | r#" |
239 | //- /main.rs | 228 | //- /main.rs |
240 | #[path = "bar/baz/module.rs"] | 229 | #[path = "bar/baz/module.rs"] |
241 | mod foo; | 230 | mod foo; |
242 | pub struct Baz; | 231 | pub struct Baz; |
243 | 232 | ||
244 | //- /bar/baz/module.rs | 233 | //- /bar/baz/module.rs |
245 | use super::Baz; | 234 | use super::Baz; |
246 | "###, | 235 | "#, |
236 | expect![[r#" | ||
237 | crate | ||
238 | Baz: t v | ||
239 | foo: t | ||
240 | |||
241 | crate::foo | ||
242 | Baz: t v | ||
243 | "#]], | ||
247 | ); | 244 | ); |
248 | |||
249 | assert_snapshot!(map, @r###" | ||
250 | â‹®crate | ||
251 | â‹®Baz: t v | ||
252 | â‹®foo: t | ||
253 | â‹® | ||
254 | â‹®crate::foo | ||
255 | â‹®Baz: t v | ||
256 | "###); | ||
257 | } | 245 | } |
258 | 246 | ||
259 | #[test] | 247 | #[test] |
260 | fn module_resolution_explicit_path_mod_rs() { | 248 | fn module_resolution_explicit_path_mod_rs() { |
261 | let map = def_map( | 249 | check( |
262 | r###" | 250 | r#" |
263 | //- /main.rs | 251 | //- /main.rs |
264 | #[path = "module/mod.rs"] | 252 | #[path = "module/mod.rs"] |
265 | mod foo; | 253 | mod foo; |
266 | 254 | ||
267 | //- /module/mod.rs | 255 | //- /module/mod.rs |
268 | pub struct Baz; | 256 | pub struct Baz; |
269 | "###, | 257 | "#, |
258 | expect![[r#" | ||
259 | crate | ||
260 | foo: t | ||
261 | |||
262 | crate::foo | ||
263 | Baz: t v | ||
264 | "#]], | ||
270 | ); | 265 | ); |
271 | |||
272 | assert_snapshot!(map, @r###" | ||
273 | â‹®crate | ||
274 | â‹®foo: t | ||
275 | â‹® | ||
276 | â‹®crate::foo | ||
277 | â‹®Baz: t v | ||
278 | "###); | ||
279 | } | 266 | } |
280 | 267 | ||
281 | #[test] | 268 | #[test] |
282 | fn module_resolution_relative_path() { | 269 | fn module_resolution_relative_path() { |
283 | let map = def_map( | 270 | check( |
284 | r###" | 271 | r#" |
285 | //- /main.rs | 272 | //- /main.rs |
286 | mod foo; | 273 | mod foo; |
287 | 274 | ||
288 | //- /foo.rs | 275 | //- /foo.rs |
289 | #[path = "./sub.rs"] | 276 | #[path = "./sub.rs"] |
290 | pub mod foo_bar; | 277 | pub mod foo_bar; |
291 | 278 | ||
292 | //- /sub.rs | 279 | //- /sub.rs |
293 | pub struct Baz; | 280 | pub struct Baz; |
294 | "###, | 281 | "#, |
282 | expect![[r#" | ||
283 | crate | ||
284 | foo: t | ||
285 | |||
286 | crate::foo | ||
287 | foo_bar: t | ||
288 | |||
289 | crate::foo::foo_bar | ||
290 | Baz: t v | ||
291 | "#]], | ||
295 | ); | 292 | ); |
296 | |||
297 | assert_snapshot!(map, @r###" | ||
298 | â‹®crate | ||
299 | â‹®foo: t | ||
300 | â‹® | ||
301 | â‹®crate::foo | ||
302 | â‹®foo_bar: t | ||
303 | â‹® | ||
304 | â‹®crate::foo::foo_bar | ||
305 | â‹®Baz: t v | ||
306 | "###); | ||
307 | } | 293 | } |
308 | 294 | ||
309 | #[test] | 295 | #[test] |
310 | fn module_resolution_relative_path_2() { | 296 | fn module_resolution_relative_path_2() { |
311 | let map = def_map( | 297 | check( |
312 | r###" | 298 | r#" |
313 | //- /main.rs | 299 | //- /main.rs |
314 | mod foo; | 300 | mod foo; |
315 | 301 | ||
316 | //- /foo/mod.rs | 302 | //- /foo/mod.rs |
317 | #[path="../sub.rs"] | 303 | #[path="../sub.rs"] |
318 | pub mod foo_bar; | 304 | pub mod foo_bar; |
319 | 305 | ||
320 | //- /sub.rs | 306 | //- /sub.rs |
321 | pub struct Baz; | 307 | pub struct Baz; |
322 | "###, | 308 | "#, |
309 | expect![[r#" | ||
310 | crate | ||
311 | foo: t | ||
312 | |||
313 | crate::foo | ||
314 | foo_bar: t | ||
315 | |||
316 | crate::foo::foo_bar | ||
317 | Baz: t v | ||
318 | "#]], | ||
323 | ); | 319 | ); |
324 | |||
325 | assert_snapshot!(map, @r###" | ||
326 | â‹®crate | ||
327 | â‹®foo: t | ||
328 | â‹® | ||
329 | â‹®crate::foo | ||
330 | â‹®foo_bar: t | ||
331 | â‹® | ||
332 | â‹®crate::foo::foo_bar | ||
333 | â‹®Baz: t v | ||
334 | "###); | ||
335 | } | 320 | } |
336 | 321 | ||
337 | #[test] | 322 | #[test] |
338 | fn module_resolution_relative_path_outside_root() { | 323 | fn module_resolution_relative_path_outside_root() { |
339 | let map = def_map( | 324 | check( |
340 | r###" | 325 | r#" |
341 | //- /main.rs | 326 | //- /main.rs |
342 | 327 | #[path="../../../../../outside.rs"] | |
343 | #[path="../../../../../outside.rs"] | 328 | mod foo; |
344 | mod foo; | 329 | "#, |
345 | "###, | 330 | expect![[r#" |
331 | crate | ||
332 | "#]], | ||
346 | ); | 333 | ); |
347 | |||
348 | assert_snapshot!(map, @r###" | ||
349 | â‹®crate | ||
350 | "###); | ||
351 | } | 334 | } |
352 | 335 | ||
353 | #[test] | 336 | #[test] |
354 | fn module_resolution_explicit_path_mod_rs_2() { | 337 | fn module_resolution_explicit_path_mod_rs_2() { |
355 | let map = def_map( | 338 | check( |
356 | r###" | 339 | r#" |
357 | //- /main.rs | 340 | //- /main.rs |
358 | #[path = "module/bar/mod.rs"] | 341 | #[path = "module/bar/mod.rs"] |
359 | mod foo; | 342 | mod foo; |
360 | 343 | ||
361 | //- /module/bar/mod.rs | 344 | //- /module/bar/mod.rs |
362 | pub struct Baz; | 345 | pub struct Baz; |
363 | "###, | 346 | "#, |
347 | expect![[r#" | ||
348 | crate | ||
349 | foo: t | ||
350 | |||
351 | crate::foo | ||
352 | Baz: t v | ||
353 | "#]], | ||
364 | ); | 354 | ); |
365 | |||
366 | assert_snapshot!(map, @r###" | ||
367 | â‹®crate | ||
368 | â‹®foo: t | ||
369 | â‹® | ||
370 | â‹®crate::foo | ||
371 | â‹®Baz: t v | ||
372 | "###); | ||
373 | } | 355 | } |
374 | 356 | ||
375 | #[test] | 357 | #[test] |
376 | fn module_resolution_explicit_path_mod_rs_with_win_separator() { | 358 | fn module_resolution_explicit_path_mod_rs_with_win_separator() { |
377 | let map = def_map( | 359 | check( |
378 | r###" | 360 | r#" |
379 | //- /main.rs | 361 | //- /main.rs |
380 | #[path = "module\bar\mod.rs"] | 362 | #[path = "module\bar\mod.rs"] |
381 | mod foo; | 363 | mod foo; |
382 | 364 | ||
383 | //- /module/bar/mod.rs | 365 | //- /module/bar/mod.rs |
384 | pub struct Baz; | 366 | pub struct Baz; |
385 | "###, | 367 | "#, |
368 | expect![[r#" | ||
369 | crate | ||
370 | foo: t | ||
371 | |||
372 | crate::foo | ||
373 | Baz: t v | ||
374 | "#]], | ||
386 | ); | 375 | ); |
387 | |||
388 | assert_snapshot!(map, @r###" | ||
389 | â‹®crate | ||
390 | â‹®foo: t | ||
391 | â‹® | ||
392 | â‹®crate::foo | ||
393 | â‹®Baz: t v | ||
394 | "###); | ||
395 | } | 376 | } |
396 | 377 | ||
397 | #[test] | 378 | #[test] |
398 | fn module_resolution_decl_inside_inline_module_with_path_attribute() { | 379 | fn module_resolution_decl_inside_inline_module_with_path_attribute() { |
399 | let map = def_map( | 380 | check( |
400 | r###" | 381 | r#" |
401 | //- /main.rs | 382 | //- /main.rs |
402 | #[path = "models"] | 383 | #[path = "models"] |
403 | mod foo { | 384 | mod foo { mod bar; } |
404 | mod bar; | 385 | |
405 | } | 386 | //- /models/bar.rs |
406 | 387 | pub struct Baz; | |
407 | //- /models/bar.rs | 388 | "#, |
408 | pub struct Baz; | 389 | expect![[r#" |
409 | "###, | 390 | crate |
391 | foo: t | ||
392 | |||
393 | crate::foo | ||
394 | bar: t | ||
395 | |||
396 | crate::foo::bar | ||
397 | Baz: t v | ||
398 | "#]], | ||
410 | ); | 399 | ); |
411 | |||
412 | assert_snapshot!(map, @r###" | ||
413 | â‹®crate | ||
414 | â‹®foo: t | ||
415 | â‹® | ||
416 | â‹®crate::foo | ||
417 | â‹®bar: t | ||
418 | â‹® | ||
419 | â‹®crate::foo::bar | ||
420 | â‹®Baz: t v | ||
421 | "###); | ||
422 | } | 400 | } |
423 | 401 | ||
424 | #[test] | 402 | #[test] |
425 | fn module_resolution_decl_inside_inline_module() { | 403 | fn module_resolution_decl_inside_inline_module() { |
426 | let map = def_map( | 404 | check( |
427 | r###" | 405 | r#" |
428 | //- /main.rs | 406 | //- /main.rs |
429 | mod foo { | 407 | mod foo { mod bar; } |
430 | mod bar; | 408 | |
431 | } | 409 | //- /foo/bar.rs |
432 | 410 | pub struct Baz; | |
433 | //- /foo/bar.rs | 411 | "#, |
434 | pub struct Baz; | 412 | expect![[r#" |
435 | "###, | 413 | crate |
414 | foo: t | ||
415 | |||
416 | crate::foo | ||
417 | bar: t | ||
418 | |||
419 | crate::foo::bar | ||
420 | Baz: t v | ||
421 | "#]], | ||
436 | ); | 422 | ); |
437 | |||
438 | assert_snapshot!(map, @r###" | ||
439 | â‹®crate | ||
440 | â‹®foo: t | ||
441 | â‹® | ||
442 | â‹®crate::foo | ||
443 | â‹®bar: t | ||
444 | â‹® | ||
445 | â‹®crate::foo::bar | ||
446 | â‹®Baz: t v | ||
447 | "###); | ||
448 | } | 423 | } |
449 | 424 | ||
450 | #[test] | 425 | #[test] |
451 | fn module_resolution_decl_inside_inline_module_2_with_path_attribute() { | 426 | fn module_resolution_decl_inside_inline_module_2_with_path_attribute() { |
452 | let map = def_map( | 427 | check( |
453 | r###" | 428 | r#" |
454 | //- /main.rs | 429 | //- /main.rs |
455 | #[path = "models/db"] | 430 | #[path = "models/db"] |
456 | mod foo { | 431 | mod foo { mod bar; } |
457 | mod bar; | 432 | |
458 | } | 433 | //- /models/db/bar.rs |
459 | 434 | pub struct Baz; | |
460 | //- /models/db/bar.rs | 435 | "#, |
461 | pub struct Baz; | 436 | expect![[r#" |
462 | "###, | 437 | crate |
438 | foo: t | ||
439 | |||
440 | crate::foo | ||
441 | bar: t | ||
442 | |||
443 | crate::foo::bar | ||
444 | Baz: t v | ||
445 | "#]], | ||
463 | ); | 446 | ); |
464 | |||
465 | assert_snapshot!(map, @r###" | ||
466 | â‹®crate | ||
467 | â‹®foo: t | ||
468 | â‹® | ||
469 | â‹®crate::foo | ||
470 | â‹®bar: t | ||
471 | â‹® | ||
472 | â‹®crate::foo::bar | ||
473 | â‹®Baz: t v | ||
474 | "###); | ||
475 | } | 447 | } |
476 | 448 | ||
477 | #[test] | 449 | #[test] |
478 | fn module_resolution_decl_inside_inline_module_3() { | 450 | fn module_resolution_decl_inside_inline_module_3() { |
479 | let map = def_map( | 451 | check( |
480 | r###" | 452 | r#" |
481 | //- /main.rs | 453 | //- /main.rs |
482 | #[path = "models/db"] | 454 | #[path = "models/db"] |
483 | mod foo { | 455 | mod foo { |
484 | #[path = "users.rs"] | 456 | #[path = "users.rs"] |
485 | mod bar; | 457 | mod bar; |
486 | } | 458 | } |
487 | 459 | ||
488 | //- /models/db/users.rs | 460 | //- /models/db/users.rs |
489 | pub struct Baz; | 461 | pub struct Baz; |
490 | "###, | 462 | "#, |
491 | ); | 463 | expect![[r#" |
464 | crate | ||
465 | foo: t | ||
492 | 466 | ||
493 | assert_snapshot!(map, @r###" | 467 | crate::foo |
494 | â‹®crate | 468 | bar: t |
495 | â‹®foo: t | 469 | |
496 | â‹® | 470 | crate::foo::bar |
497 | â‹®crate::foo | 471 | Baz: t v |
498 | â‹®bar: t | 472 | "#]], |
499 | â‹® | 473 | ); |
500 | â‹®crate::foo::bar | ||
501 | â‹®Baz: t v | ||
502 | "###); | ||
503 | } | 474 | } |
504 | 475 | ||
505 | #[test] | 476 | #[test] |
506 | fn module_resolution_decl_inside_inline_module_empty_path() { | 477 | fn module_resolution_decl_inside_inline_module_empty_path() { |
507 | let map = def_map( | 478 | check( |
508 | r###" | 479 | r#" |
509 | //- /main.rs | 480 | //- /main.rs |
510 | #[path = ""] | 481 | #[path = ""] |
511 | mod foo { | 482 | mod foo { |
512 | #[path = "users.rs"] | 483 | #[path = "users.rs"] |
513 | mod bar; | 484 | mod bar; |
514 | } | 485 | } |
515 | |||
516 | //- /users.rs | ||
517 | pub struct Baz; | ||
518 | "###, | ||
519 | ); | ||
520 | 486 | ||
521 | assert_snapshot!(map, @r###" | 487 | //- /users.rs |
522 | â‹®crate | 488 | pub struct Baz; |
523 | â‹®foo: t | 489 | "#, |
524 | â‹® | 490 | expect![[r#" |
525 | â‹®crate::foo | 491 | crate |
526 | â‹®bar: t | 492 | foo: t |
527 | â‹® | 493 | |
528 | â‹®crate::foo::bar | 494 | crate::foo |
529 | â‹®Baz: t v | 495 | bar: t |
530 | "###); | 496 | |
497 | crate::foo::bar | ||
498 | Baz: t v | ||
499 | "#]], | ||
500 | ); | ||
531 | } | 501 | } |
532 | 502 | ||
533 | #[test] | 503 | #[test] |
534 | fn module_resolution_decl_empty_path() { | 504 | fn module_resolution_decl_empty_path() { |
535 | let map = def_map( | 505 | check( |
536 | r###" | 506 | r#" |
537 | //- /main.rs | 507 | //- /main.rs |
538 | #[path = ""] // Should try to read `/` (a directory) | 508 | #[path = ""] // Should try to read `/` (a directory) |
539 | mod foo; | 509 | mod foo; |
540 | 510 | ||
541 | //- /foo.rs | 511 | //- /foo.rs |
542 | pub struct Baz; | 512 | pub struct Baz; |
543 | "###, | 513 | "#, |
514 | expect![[r#" | ||
515 | crate | ||
516 | "#]], | ||
544 | ); | 517 | ); |
545 | |||
546 | assert_snapshot!(map, @r###" | ||
547 | â‹®crate | ||
548 | "###); | ||
549 | } | 518 | } |
550 | 519 | ||
551 | #[test] | 520 | #[test] |
552 | fn module_resolution_decl_inside_inline_module_relative_path() { | 521 | fn module_resolution_decl_inside_inline_module_relative_path() { |
553 | let map = def_map( | 522 | check( |
554 | r###" | 523 | r#" |
555 | //- /main.rs | 524 | //- /main.rs |
556 | #[path = "./models"] | 525 | #[path = "./models"] |
557 | mod foo { | 526 | mod foo { mod bar; } |
558 | mod bar; | 527 | |
559 | } | 528 | //- /models/bar.rs |
560 | 529 | pub struct Baz; | |
561 | //- /models/bar.rs | 530 | "#, |
562 | pub struct Baz; | 531 | expect![[r#" |
563 | "###, | 532 | crate |
533 | foo: t | ||
534 | |||
535 | crate::foo | ||
536 | bar: t | ||
537 | |||
538 | crate::foo::bar | ||
539 | Baz: t v | ||
540 | "#]], | ||
564 | ); | 541 | ); |
565 | |||
566 | assert_snapshot!(map, @r###" | ||
567 | â‹®crate | ||
568 | â‹®foo: t | ||
569 | â‹® | ||
570 | â‹®crate::foo | ||
571 | â‹®bar: t | ||
572 | â‹® | ||
573 | â‹®crate::foo::bar | ||
574 | â‹®Baz: t v | ||
575 | "###); | ||
576 | } | 542 | } |
577 | 543 | ||
578 | #[test] | 544 | #[test] |
579 | fn module_resolution_decl_inside_inline_module_in_crate_root() { | 545 | fn module_resolution_decl_inside_inline_module_in_crate_root() { |
580 | let map = def_map( | 546 | check( |
581 | r###" | 547 | r#" |
582 | //- /main.rs | 548 | //- /main.rs |
583 | mod foo { | 549 | mod foo { |
584 | #[path = "baz.rs"] | 550 | #[path = "baz.rs"] |
585 | mod bar; | 551 | mod bar; |
586 | } | 552 | } |
587 | use self::foo::bar::Baz; | 553 | use self::foo::bar::Baz; |
588 | 554 | ||
589 | //- /foo/baz.rs | 555 | //- /foo/baz.rs |
590 | pub struct Baz; | 556 | pub struct Baz; |
591 | "###, | 557 | "#, |
558 | expect![[r#" | ||
559 | crate | ||
560 | Baz: t v | ||
561 | foo: t | ||
562 | |||
563 | crate::foo | ||
564 | bar: t | ||
565 | |||
566 | crate::foo::bar | ||
567 | Baz: t v | ||
568 | "#]], | ||
592 | ); | 569 | ); |
593 | |||
594 | assert_snapshot!(map, @r###" | ||
595 | â‹®crate | ||
596 | â‹®Baz: t v | ||
597 | â‹®foo: t | ||
598 | â‹® | ||
599 | â‹®crate::foo | ||
600 | â‹®bar: t | ||
601 | â‹® | ||
602 | â‹®crate::foo::bar | ||
603 | â‹®Baz: t v | ||
604 | "###); | ||
605 | } | 570 | } |
606 | 571 | ||
607 | #[test] | 572 | #[test] |
608 | fn module_resolution_decl_inside_inline_module_in_mod_rs() { | 573 | fn module_resolution_decl_inside_inline_module_in_mod_rs() { |
609 | let map = def_map( | 574 | check( |
610 | r###" | 575 | r#" |
611 | //- /main.rs | 576 | //- /main.rs |
612 | mod foo; | 577 | mod foo; |
578 | |||
579 | //- /foo/mod.rs | ||
580 | mod bar { | ||
581 | #[path = "qwe.rs"] | ||
582 | pub mod baz; | ||
583 | } | ||
584 | use self::bar::baz::Baz; | ||
613 | 585 | ||
614 | //- /foo/mod.rs | 586 | //- /foo/bar/qwe.rs |
615 | mod bar { | 587 | pub struct Baz; |
616 | #[path = "qwe.rs"] | 588 | "#, |
617 | pub mod baz; | 589 | expect![[r#" |
618 | } | 590 | crate |
619 | use self::bar::baz::Baz; | 591 | foo: t |
620 | 592 | ||
621 | //- /foo/bar/qwe.rs | 593 | crate::foo |
622 | pub struct Baz; | 594 | Baz: t v |
623 | "###, | 595 | bar: t |
624 | ); | 596 | |
597 | crate::foo::bar | ||
598 | baz: t | ||
625 | 599 | ||
626 | assert_snapshot!(map, @r###" | 600 | crate::foo::bar::baz |
627 | â‹®crate | 601 | Baz: t v |
628 | â‹®foo: t | 602 | "#]], |
629 | â‹® | 603 | ); |
630 | â‹®crate::foo | ||
631 | â‹®Baz: t v | ||
632 | â‹®bar: t | ||
633 | â‹® | ||
634 | â‹®crate::foo::bar | ||
635 | â‹®baz: t | ||
636 | â‹® | ||
637 | â‹®crate::foo::bar::baz | ||
638 | â‹®Baz: t v | ||
639 | "###); | ||
640 | } | 604 | } |
641 | 605 | ||
642 | #[test] | 606 | #[test] |
643 | fn module_resolution_decl_inside_inline_module_in_non_crate_root() { | 607 | fn module_resolution_decl_inside_inline_module_in_non_crate_root() { |
644 | let map = def_map( | 608 | check( |
645 | r###" | 609 | r#" |
646 | //- /main.rs | 610 | //- /main.rs |
647 | mod foo; | 611 | mod foo; |
612 | |||
613 | //- /foo.rs | ||
614 | mod bar { | ||
615 | #[path = "qwe.rs"] | ||
616 | pub mod baz; | ||
617 | } | ||
618 | use self::bar::baz::Baz; | ||
648 | 619 | ||
649 | //- /foo.rs | 620 | //- /foo/bar/qwe.rs |
650 | mod bar { | 621 | pub struct Baz; |
651 | #[path = "qwe.rs"] | 622 | "#, |
652 | pub mod baz; | 623 | expect![[r#" |
653 | } | 624 | crate |
654 | use self::bar::baz::Baz; | 625 | foo: t |
655 | |||
656 | //- /foo/bar/qwe.rs | ||
657 | pub struct Baz; | ||
658 | "###, | ||
659 | ); | ||
660 | 626 | ||
661 | assert_snapshot!(map, @r###" | 627 | crate::foo |
662 | â‹®crate | 628 | Baz: t v |
663 | â‹®foo: t | 629 | bar: t |
664 | â‹® | 630 | |
665 | â‹®crate::foo | 631 | crate::foo::bar |
666 | â‹®Baz: t v | 632 | baz: t |
667 | â‹®bar: t | 633 | |
668 | â‹® | 634 | crate::foo::bar::baz |
669 | â‹®crate::foo::bar | 635 | Baz: t v |
670 | â‹®baz: t | 636 | "#]], |
671 | â‹® | 637 | ); |
672 | â‹®crate::foo::bar::baz | ||
673 | â‹®Baz: t v | ||
674 | "###); | ||
675 | } | 638 | } |
676 | 639 | ||
677 | #[test] | 640 | #[test] |
678 | fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() { | 641 | fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() { |
679 | let map = def_map( | 642 | check( |
680 | r###" | 643 | r#" |
681 | //- /main.rs | 644 | //- /main.rs |
682 | mod foo; | 645 | mod foo; |
646 | |||
647 | //- /foo.rs | ||
648 | #[path = "bar"] | ||
649 | mod bar { | ||
650 | pub mod baz; | ||
651 | } | ||
652 | use self::bar::baz::Baz; | ||
683 | 653 | ||
684 | //- /foo.rs | 654 | //- /bar/baz.rs |
685 | #[path = "bar"] | 655 | pub struct Baz; |
686 | mod bar { | 656 | "#, |
687 | pub mod baz; | 657 | expect![[r#" |
688 | } | 658 | crate |
689 | use self::bar::baz::Baz; | 659 | foo: t |
690 | 660 | ||
691 | //- /bar/baz.rs | 661 | crate::foo |
692 | pub struct Baz; | 662 | Baz: t v |
693 | "###, | 663 | bar: t |
694 | ); | ||
695 | 664 | ||
696 | assert_snapshot!(map, @r###" | 665 | crate::foo::bar |
697 | â‹®crate | 666 | baz: t |
698 | â‹®foo: t | 667 | |
699 | â‹® | 668 | crate::foo::bar::baz |
700 | â‹®crate::foo | 669 | Baz: t v |
701 | â‹®Baz: t v | 670 | "#]], |
702 | â‹®bar: t | 671 | ); |
703 | â‹® | ||
704 | â‹®crate::foo::bar | ||
705 | â‹®baz: t | ||
706 | â‹® | ||
707 | â‹®crate::foo::bar::baz | ||
708 | â‹®Baz: t v | ||
709 | "###); | ||
710 | } | 672 | } |
711 | 673 | ||
712 | #[test] | 674 | #[test] |
@@ -724,116 +686,111 @@ fn unresolved_module_diagnostics() { | |||
724 | 686 | ||
725 | let crate_def_map = db.crate_def_map(krate); | 687 | let crate_def_map = db.crate_def_map(krate); |
726 | 688 | ||
727 | insta::assert_debug_snapshot!( | 689 | expect![[r#" |
728 | crate_def_map.diagnostics, | 690 | [ |
729 | @r###" | 691 | UnresolvedModule { |
730 | [ | 692 | module: Idx::<ModuleData>(0), |
731 | UnresolvedModule { | 693 | declaration: InFile { |
732 | module: Idx::<ModuleData>(0), | 694 | file_id: HirFileId( |
733 | declaration: InFile { | ||
734 | file_id: HirFileId( | ||
735 | FileId( | ||
736 | FileId( | 695 | FileId( |
737 | 0, | 696 | FileId( |
697 | 0, | ||
698 | ), | ||
738 | ), | 699 | ), |
739 | ), | 700 | ), |
740 | ), | 701 | value: FileAstId::<ra_syntax::ast::generated::nodes::Module>(1), |
741 | value: FileAstId::<ra_syntax::ast::generated::nodes::Module>(1), | 702 | }, |
703 | candidate: "bar.rs", | ||
742 | }, | 704 | }, |
743 | candidate: "bar.rs", | 705 | ] |
744 | }, | 706 | "#]] |
745 | ] | 707 | .assert_debug_eq(&crate_def_map.diagnostics); |
746 | "### | ||
747 | ); | ||
748 | } | 708 | } |
749 | 709 | ||
750 | #[test] | 710 | #[test] |
751 | fn module_resolution_decl_inside_module_in_non_crate_root_2() { | 711 | fn module_resolution_decl_inside_module_in_non_crate_root_2() { |
752 | let map = def_map( | 712 | check( |
753 | r###" | 713 | r#" |
754 | //- /main.rs | 714 | //- /main.rs |
755 | #[path="module/m2.rs"] | 715 | #[path="module/m2.rs"] |
756 | mod module; | 716 | mod module; |
757 | 717 | ||
758 | //- /module/m2.rs | 718 | //- /module/m2.rs |
759 | pub mod submod; | 719 | pub mod submod; |
760 | 720 | ||
761 | //- /module/submod.rs | 721 | //- /module/submod.rs |
762 | pub struct Baz; | 722 | pub struct Baz; |
763 | "###, | 723 | "#, |
724 | expect![[r#" | ||
725 | crate | ||
726 | module: t | ||
727 | |||
728 | crate::module | ||
729 | submod: t | ||
730 | |||
731 | crate::module::submod | ||
732 | Baz: t v | ||
733 | "#]], | ||
764 | ); | 734 | ); |
765 | |||
766 | assert_snapshot!(map, @r###" | ||
767 | â‹®crate | ||
768 | â‹®module: t | ||
769 | â‹® | ||
770 | â‹®crate::module | ||
771 | â‹®submod: t | ||
772 | â‹® | ||
773 | â‹®crate::module::submod | ||
774 | â‹®Baz: t v | ||
775 | "###); | ||
776 | } | 735 | } |
777 | 736 | ||
778 | #[test] | 737 | #[test] |
779 | fn nested_out_of_line_module() { | 738 | fn nested_out_of_line_module() { |
780 | let map = def_map( | 739 | check( |
781 | r###" | 740 | r#" |
782 | //- /lib.rs | 741 | //- /lib.rs |
783 | mod a { | 742 | mod a { |
784 | mod b { | 743 | mod b { |
785 | mod c; | 744 | mod c; |
786 | } | 745 | } |
787 | } | 746 | } |
788 | |||
789 | //- /a/b/c.rs | ||
790 | struct X; | ||
791 | "###, | ||
792 | ); | ||
793 | 747 | ||
794 | assert_snapshot!(map, @r###" | 748 | //- /a/b/c.rs |
795 | â‹®crate | 749 | struct X; |
796 | â‹®a: t | 750 | "#, |
797 | â‹® | 751 | expect![[r#" |
798 | â‹®crate::a | 752 | crate |
799 | â‹®b: t | 753 | a: t |
800 | â‹® | 754 | |
801 | â‹®crate::a::b | 755 | crate::a |
802 | â‹®c: t | 756 | b: t |
803 | â‹® | 757 | |
804 | â‹®crate::a::b::c | 758 | crate::a::b |
805 | â‹®X: t v | 759 | c: t |
806 | "###); | 760 | |
761 | crate::a::b::c | ||
762 | X: t v | ||
763 | "#]], | ||
764 | ); | ||
807 | } | 765 | } |
808 | 766 | ||
809 | #[test] | 767 | #[test] |
810 | fn nested_out_of_line_module_with_path() { | 768 | fn nested_out_of_line_module_with_path() { |
811 | let map = def_map( | 769 | check( |
812 | r###" | 770 | r#" |
813 | //- /lib.rs | 771 | //- /lib.rs |
814 | mod a { | 772 | mod a { |
815 | #[path = "d/e"] | 773 | #[path = "d/e"] |
816 | mod b { | 774 | mod b { |
817 | mod c; | 775 | mod c; |
818 | } | 776 | } |
819 | } | 777 | } |
820 | 778 | ||
821 | //- /a/d/e/c.rs | 779 | //- /a/d/e/c.rs |
822 | struct X; | 780 | struct X; |
823 | "###, | 781 | "#, |
824 | ); | 782 | expect![[r#" |
783 | crate | ||
784 | a: t | ||
825 | 785 | ||
826 | assert_snapshot!(map, @r###" | 786 | crate::a |
827 | â‹®crate | 787 | b: t |
828 | â‹®a: t | 788 | |
829 | â‹® | 789 | crate::a::b |
830 | â‹®crate::a | 790 | c: t |
831 | â‹®b: t | 791 | |
832 | â‹® | 792 | crate::a::b::c |
833 | â‹®crate::a::b | 793 | X: t v |
834 | â‹®c: t | 794 | "#]], |
835 | â‹® | 795 | ); |
836 | â‹®crate::a::b::c | ||
837 | â‹®X: t v | ||
838 | "###); | ||
839 | } | 796 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests/primitives.rs b/crates/ra_hir_def/src/nameres/tests/primitives.rs index 0e2708658..215e8952d 100644 --- a/crates/ra_hir_def/src/nameres/tests/primitives.rs +++ b/crates/ra_hir_def/src/nameres/tests/primitives.rs | |||
@@ -2,23 +2,22 @@ use super::*; | |||
2 | 2 | ||
3 | #[test] | 3 | #[test] |
4 | fn primitive_reexport() { | 4 | fn primitive_reexport() { |
5 | let map = def_map( | 5 | check( |
6 | " | 6 | r#" |
7 | //- /lib.rs | 7 | //- /lib.rs |
8 | mod foo; | 8 | mod foo; |
9 | use foo::int; | 9 | use foo::int; |
10 | 10 | ||
11 | //- /foo.rs | 11 | //- /foo.rs |
12 | pub use i32 as int; | 12 | pub use i32 as int; |
13 | ", | 13 | "#, |
14 | ); | 14 | expect![[r#" |
15 | assert_snapshot!(map, @r###" | 15 | crate |
16 | â‹®crate | 16 | foo: t |
17 | â‹®foo: t | 17 | int: t |
18 | â‹®int: t | 18 | |
19 | â‹® | 19 | crate::foo |
20 | â‹®crate::foo | 20 | int: t |
21 | â‹®int: t | 21 | "#]], |
22 | "### | ||
23 | ); | 22 | ); |
24 | } | 23 | } |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 190d6d98d..68b9f89c3 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -67,7 +67,7 @@ impl ModPath { | |||
67 | 67 | ||
68 | /// Calls `cb` with all paths, represented by this use item. | 68 | /// Calls `cb` with all paths, represented by this use item. |
69 | pub(crate) fn expand_use_item( | 69 | pub(crate) fn expand_use_item( |
70 | item_src: InFile<ast::UseItem>, | 70 | item_src: InFile<ast::Use>, |
71 | hygiene: &Hygiene, | 71 | hygiene: &Hygiene, |
72 | mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>), | 72 | mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>), |
73 | ) { | 73 | ) { |
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index 6a0c019fd..07d17916a 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs | |||
@@ -9,7 +9,7 @@ use hir_expand::{ | |||
9 | hygiene::Hygiene, | 9 | hygiene::Hygiene, |
10 | name::{name, AsName}, | 10 | name::{name, AsName}, |
11 | }; | 11 | }; |
12 | use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}; | 12 | use ra_syntax::ast::{self, AstNode, TypeBoundsOwner}; |
13 | 13 | ||
14 | use super::AssociatedTypeBinding; | 14 | use super::AssociatedTypeBinding; |
15 | use crate::{ | 15 | use crate::{ |
@@ -189,14 +189,14 @@ fn lower_generic_args_from_fn_path( | |||
189 | if let Some(params) = params { | 189 | if let Some(params) = params { |
190 | let mut param_types = Vec::new(); | 190 | let mut param_types = Vec::new(); |
191 | for param in params.params() { | 191 | for param in params.params() { |
192 | let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type()); | 192 | let type_ref = TypeRef::from_ast_opt(&ctx, param.ty()); |
193 | param_types.push(type_ref); | 193 | param_types.push(type_ref); |
194 | } | 194 | } |
195 | let arg = GenericArg::Type(TypeRef::Tuple(param_types)); | 195 | let arg = GenericArg::Type(TypeRef::Tuple(param_types)); |
196 | args.push(arg); | 196 | args.push(arg); |
197 | } | 197 | } |
198 | if let Some(ret_type) = ret_type { | 198 | if let Some(ret_type) = ret_type { |
199 | let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref()); | 199 | let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty()); |
200 | bindings.push(AssociatedTypeBinding { | 200 | bindings.push(AssociatedTypeBinding { |
201 | name: name![Output], | 201 | name: name![Output], |
202 | type_ref: Some(type_ref), | 202 | type_ref: Some(type_ref), |
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs index 7cc655487..794be45e8 100644 --- a/crates/ra_hir_def/src/path/lower/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs | |||
@@ -31,7 +31,7 @@ pub(crate) fn lower_use_tree( | |||
31 | lower_use_tree(prefix.clone(), child_tree, hygiene, cb); | 31 | lower_use_tree(prefix.clone(), child_tree, hygiene, cb); |
32 | } | 32 | } |
33 | } else { | 33 | } else { |
34 | let alias = tree.alias().map(|a| { | 34 | let alias = tree.rename().map(|a| { |
35 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | 35 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) |
36 | }); | 36 | }); |
37 | let is_glob = tree.star_token().is_some(); | 37 | let is_glob = tree.star_token().is_some(); |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 15fdd9019..0bf51eb7b 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -511,11 +511,9 @@ impl Scope { | |||
511 | }); | 511 | }); |
512 | } | 512 | } |
513 | } | 513 | } |
514 | Scope::LocalItemsScope(body) => { | 514 | Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| { |
515 | body.item_scope.entries_without_primitives().for_each(|(name, def)| { | 515 | f(name.clone(), ScopeDef::PerNs(def)); |
516 | f(name.clone(), ScopeDef::PerNs(def)); | 516 | }), |
517 | }) | ||
518 | } | ||
519 | Scope::GenericParams { params, def } => { | 517 | Scope::GenericParams { params, def } => { |
520 | for (local_id, param) in params.types.iter() { | 518 | for (local_id, param) in params.types.iter() { |
521 | if let Some(name) = ¶m.name { | 519 | if let Some(name) = ¶m.name { |
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs index 4581d8745..339f819b8 100644 --- a/crates/ra_hir_def/src/test_db.rs +++ b/crates/ra_hir_def/src/test_db.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Database used for testing `hir_def`. | 1 | //! Database used for testing `hir_def`. |
2 | 2 | ||
3 | use std::{ | 3 | use std::{ |
4 | panic, | 4 | fmt, panic, |
5 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
6 | }; | 6 | }; |
7 | 7 | ||
@@ -18,10 +18,10 @@ use crate::db::DefDatabase; | |||
18 | crate::db::InternDatabaseStorage, | 18 | crate::db::InternDatabaseStorage, |
19 | crate::db::DefDatabaseStorage | 19 | crate::db::DefDatabaseStorage |
20 | )] | 20 | )] |
21 | #[derive(Debug, Default)] | 21 | #[derive(Default)] |
22 | pub struct TestDB { | 22 | pub struct TestDB { |
23 | runtime: salsa::Runtime<TestDB>, | 23 | storage: salsa::Storage<TestDB>, |
24 | events: Mutex<Option<Vec<salsa::Event<TestDB>>>>, | 24 | events: Mutex<Option<Vec<salsa::Event>>>, |
25 | } | 25 | } |
26 | 26 | ||
27 | impl Upcast<dyn AstDatabase> for TestDB { | 27 | impl Upcast<dyn AstDatabase> for TestDB { |
@@ -37,20 +37,20 @@ impl Upcast<dyn DefDatabase> for TestDB { | |||
37 | } | 37 | } |
38 | 38 | ||
39 | impl salsa::Database for TestDB { | 39 | impl salsa::Database for TestDB { |
40 | fn salsa_runtime(&self) -> &salsa::Runtime<Self> { | 40 | fn salsa_event(&self, event: salsa::Event) { |
41 | &self.runtime | ||
42 | } | ||
43 | fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> { | ||
44 | &mut self.runtime | ||
45 | } | ||
46 | fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) { | ||
47 | let mut events = self.events.lock().unwrap(); | 41 | let mut events = self.events.lock().unwrap(); |
48 | if let Some(events) = &mut *events { | 42 | if let Some(events) = &mut *events { |
49 | events.push(event()); | 43 | events.push(event); |
50 | } | 44 | } |
51 | } | 45 | } |
52 | } | 46 | } |
53 | 47 | ||
48 | impl fmt::Debug for TestDB { | ||
49 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
50 | f.debug_struct("TestDB").finish() | ||
51 | } | ||
52 | } | ||
53 | |||
54 | impl panic::RefUnwindSafe for TestDB {} | 54 | impl panic::RefUnwindSafe for TestDB {} |
55 | 55 | ||
56 | impl FileLoader for TestDB { | 56 | impl FileLoader for TestDB { |
@@ -78,7 +78,7 @@ impl TestDB { | |||
78 | panic!("Can't find module for file") | 78 | panic!("Can't find module for file") |
79 | } | 79 | } |
80 | 80 | ||
81 | pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> { | 81 | pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> { |
82 | *self.events.lock().unwrap() = Some(Vec::new()); | 82 | *self.events.lock().unwrap() = Some(Vec::new()); |
83 | f(); | 83 | f(); |
84 | self.events.lock().unwrap().take().unwrap() | 84 | self.events.lock().unwrap().take().unwrap() |
@@ -92,7 +92,7 @@ impl TestDB { | |||
92 | // This pretty horrible, but `Debug` is the only way to inspect | 92 | // This pretty horrible, but `Debug` is the only way to inspect |
93 | // QueryDescriptor at the moment. | 93 | // QueryDescriptor at the moment. |
94 | salsa::EventKind::WillExecute { database_key } => { | 94 | salsa::EventKind::WillExecute { database_key } => { |
95 | Some(format!("{:?}", database_key)) | 95 | Some(format!("{:?}", database_key.debug(self))) |
96 | } | 96 | } |
97 | _ => None, | 97 | _ => None, |
98 | }) | 98 | }) |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 86a77b704..a5dc10eac 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | 1 | //! HIR for references to types. Paths in these are not yet resolved. They can |
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | 3 | ||
4 | use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; | 4 | use ra_syntax::ast::{self}; |
5 | 5 | ||
6 | use crate::{body::LowerCtx, path::Path}; | 6 | use crate::{body::LowerCtx, path::Path}; |
7 | 7 | ||
@@ -63,7 +63,7 @@ pub enum TypeRef { | |||
63 | Array(Box<TypeRef> /*, Expr*/), | 63 | Array(Box<TypeRef> /*, Expr*/), |
64 | Slice(Box<TypeRef>), | 64 | Slice(Box<TypeRef>), |
65 | /// A fn pointer. Last element of the vector is the return type. | 65 | /// A fn pointer. Last element of the vector is the return type. |
66 | Fn(Vec<TypeRef>), | 66 | Fn(Vec<TypeRef>, bool /*varargs*/), |
67 | // For | 67 | // For |
68 | ImplTrait(Vec<TypeBound>), | 68 | ImplTrait(Vec<TypeBound>), |
69 | DynTrait(Vec<TypeBound>), | 69 | DynTrait(Vec<TypeBound>), |
@@ -82,7 +82,7 @@ impl TypeRef { | |||
82 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. | 82 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. |
83 | pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self { | 83 | pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self { |
84 | match node { | 84 | match node { |
85 | ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()), | 85 | ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()), |
86 | ast::TypeRef::TupleType(inner) => { | 86 | ast::TypeRef::TupleType(inner) => { |
87 | TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect()) | 87 | TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect()) |
88 | } | 88 | } |
@@ -96,18 +96,18 @@ impl TypeRef { | |||
96 | .unwrap_or(TypeRef::Error) | 96 | .unwrap_or(TypeRef::Error) |
97 | } | 97 | } |
98 | ast::TypeRef::PointerType(inner) => { | 98 | ast::TypeRef::PointerType(inner) => { |
99 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref()); | 99 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); |
100 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 100 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
101 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | 101 | TypeRef::RawPtr(Box::new(inner_ty), mutability) |
102 | } | 102 | } |
103 | ast::TypeRef::ArrayType(inner) => { | 103 | ast::TypeRef::ArrayType(inner) => { |
104 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref()))) | 104 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) |
105 | } | 105 | } |
106 | ast::TypeRef::SliceType(inner) => { | 106 | ast::TypeRef::SliceType(inner) => { |
107 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref()))) | 107 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) |
108 | } | 108 | } |
109 | ast::TypeRef::ReferenceType(inner) => { | 109 | ast::TypeRef::ReferenceType(inner) => { |
110 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref()); | 110 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); |
111 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 111 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
112 | TypeRef::Reference(Box::new(inner_ty), mutability) | 112 | TypeRef::Reference(Box::new(inner_ty), mutability) |
113 | } | 113 | } |
@@ -115,22 +115,24 @@ impl TypeRef { | |||
115 | ast::TypeRef::FnPointerType(inner) => { | 115 | ast::TypeRef::FnPointerType(inner) => { |
116 | let ret_ty = inner | 116 | let ret_ty = inner |
117 | .ret_type() | 117 | .ret_type() |
118 | .and_then(|rt| rt.type_ref()) | 118 | .and_then(|rt| rt.ty()) |
119 | .map(|it| TypeRef::from_ast(ctx, it)) | 119 | .map(|it| TypeRef::from_ast(ctx, it)) |
120 | .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); | 120 | .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); |
121 | let mut is_varargs = false; | ||
121 | let mut params = if let Some(pl) = inner.param_list() { | 122 | let mut params = if let Some(pl) = inner.param_list() { |
122 | pl.params() | 123 | if let Some(param) = pl.params().last() { |
123 | .map(|p| p.ascribed_type()) | 124 | is_varargs = param.dotdotdot_token().is_some(); |
124 | .map(|it| TypeRef::from_ast_opt(&ctx, it)) | 125 | } |
125 | .collect() | 126 | |
127 | pl.params().map(|p| p.ty()).map(|it| TypeRef::from_ast_opt(&ctx, it)).collect() | ||
126 | } else { | 128 | } else { |
127 | Vec::new() | 129 | Vec::new() |
128 | }; | 130 | }; |
129 | params.push(ret_ty); | 131 | params.push(ret_ty); |
130 | TypeRef::Fn(params) | 132 | TypeRef::Fn(params, is_varargs) |
131 | } | 133 | } |
132 | // for types are close enough for our purposes to the inner type for now... | 134 | // for types are close enough for our purposes to the inner type for now... |
133 | ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()), | 135 | ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()), |
134 | ast::TypeRef::ImplTraitType(inner) => { | 136 | ast::TypeRef::ImplTraitType(inner) => { |
135 | TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) | 137 | TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) |
136 | } | 138 | } |
@@ -158,7 +160,9 @@ impl TypeRef { | |||
158 | fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { | 160 | fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { |
159 | f(type_ref); | 161 | f(type_ref); |
160 | match type_ref { | 162 | match type_ref { |
161 | TypeRef::Fn(types) | TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), | 163 | TypeRef::Fn(types, _) | TypeRef::Tuple(types) => { |
164 | types.iter().for_each(|t| go(t, f)) | ||
165 | } | ||
162 | TypeRef::RawPtr(type_ref, _) | 166 | TypeRef::RawPtr(type_ref, _) |
163 | | TypeRef::Reference(type_ref, _) | 167 | | TypeRef::Reference(type_ref, _) |
164 | | TypeRef::Array(type_ref) | 168 | | TypeRef::Array(type_ref) |
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs index 8136cb50c..1abffb4c3 100644 --- a/crates/ra_hir_def/src/visibility.rs +++ b/crates/ra_hir_def/src/visibility.rs | |||
@@ -5,6 +5,7 @@ use ra_syntax::ast; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | nameres::CrateDefMap, | ||
8 | path::{ModPath, PathKind}, | 9 | path::{ModPath, PathKind}, |
9 | ModuleId, | 10 | ModuleId, |
10 | }; | 11 | }; |
@@ -115,7 +116,7 @@ impl Visibility { | |||
115 | 116 | ||
116 | pub(crate) fn is_visible_from_def_map( | 117 | pub(crate) fn is_visible_from_def_map( |
117 | self, | 118 | self, |
118 | def_map: &crate::nameres::CrateDefMap, | 119 | def_map: &CrateDefMap, |
119 | from_module: crate::LocalModuleId, | 120 | from_module: crate::LocalModuleId, |
120 | ) -> bool { | 121 | ) -> bool { |
121 | let to_module = match self { | 122 | let to_module = match self { |
@@ -129,4 +130,42 @@ impl Visibility { | |||
129 | }); | 130 | }); |
130 | ancestors.any(|m| m == to_module.local_id) | 131 | ancestors.any(|m| m == to_module.local_id) |
131 | } | 132 | } |
133 | |||
134 | /// Returns the most permissive visibility of `self` and `other`. | ||
135 | /// | ||
136 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only | ||
137 | /// visible in unrelated modules). | ||
138 | pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> { | ||
139 | match (self, other) { | ||
140 | (Visibility::Module(_), Visibility::Public) | ||
141 | | (Visibility::Public, Visibility::Module(_)) | ||
142 | | (Visibility::Public, Visibility::Public) => Some(Visibility::Public), | ||
143 | (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { | ||
144 | if mod_a.krate != mod_b.krate { | ||
145 | return None; | ||
146 | } | ||
147 | |||
148 | let mut a_ancestors = std::iter::successors(Some(mod_a.local_id), |m| { | ||
149 | let parent_id = def_map[*m].parent?; | ||
150 | Some(parent_id) | ||
151 | }); | ||
152 | let mut b_ancestors = std::iter::successors(Some(mod_b.local_id), |m| { | ||
153 | let parent_id = def_map[*m].parent?; | ||
154 | Some(parent_id) | ||
155 | }); | ||
156 | |||
157 | if a_ancestors.any(|m| m == mod_b.local_id) { | ||
158 | // B is above A | ||
159 | return Some(Visibility::Module(mod_b)); | ||
160 | } | ||
161 | |||
162 | if b_ancestors.any(|m| m == mod_a.local_id) { | ||
163 | // A is above B | ||
164 | return Some(Visibility::Module(mod_a)); | ||
165 | } | ||
166 | |||
167 | None | ||
168 | } | ||
169 | } | ||
170 | } | ||
132 | } | 171 | } |