diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/hir_def/src/adt.rs | 10 | ||||
-rw-r--r-- | crates/hir_def/src/attr.rs | 48 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 19 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 129 | ||||
-rw-r--r-- | crates/hir_def/src/data.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/diagnostics.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 36 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 35 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 33 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 48 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 11 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 9 |
14 files changed, 269 insertions, 145 deletions
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index c2d99280f..475d337f3 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | once_cell = "1.3.1" | 15 | once_cell = "1.3.1" |
16 | rustc-hash = "1.1.0" | 16 | rustc-hash = "1.1.0" |
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index efbde17d8..1b9bb8235 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs | |||
@@ -31,12 +31,14 @@ pub struct StructData { | |||
31 | pub name: Name, | 31 | pub name: Name, |
32 | pub variant_data: Arc<VariantData>, | 32 | pub variant_data: Arc<VariantData>, |
33 | pub repr: Option<ReprKind>, | 33 | pub repr: Option<ReprKind>, |
34 | pub visibility: RawVisibility, | ||
34 | } | 35 | } |
35 | 36 | ||
36 | #[derive(Debug, Clone, PartialEq, Eq)] | 37 | #[derive(Debug, Clone, PartialEq, Eq)] |
37 | pub struct EnumData { | 38 | pub struct EnumData { |
38 | pub name: Name, | 39 | pub name: Name, |
39 | pub variants: Arena<EnumVariantData>, | 40 | pub variants: Arena<EnumVariantData>, |
41 | pub visibility: RawVisibility, | ||
40 | } | 42 | } |
41 | 43 | ||
42 | #[derive(Debug, Clone, PartialEq, Eq)] | 44 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -102,6 +104,7 @@ impl StructData { | |||
102 | name: strukt.name.clone(), | 104 | name: strukt.name.clone(), |
103 | variant_data: Arc::new(variant_data), | 105 | variant_data: Arc::new(variant_data), |
104 | repr, | 106 | repr, |
107 | visibility: item_tree[strukt.visibility].clone(), | ||
105 | }) | 108 | }) |
106 | } | 109 | } |
107 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { | 110 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { |
@@ -118,6 +121,7 @@ impl StructData { | |||
118 | name: union.name.clone(), | 121 | name: union.name.clone(), |
119 | variant_data: Arc::new(variant_data), | 122 | variant_data: Arc::new(variant_data), |
120 | repr, | 123 | repr, |
124 | visibility: item_tree[union.visibility].clone(), | ||
121 | }) | 125 | }) |
122 | } | 126 | } |
123 | } | 127 | } |
@@ -150,7 +154,11 @@ impl EnumData { | |||
150 | } | 154 | } |
151 | } | 155 | } |
152 | 156 | ||
153 | Arc::new(EnumData { name: enum_.name.clone(), variants }) | 157 | Arc::new(EnumData { |
158 | name: enum_.name.clone(), | ||
159 | variants, | ||
160 | visibility: item_tree[enum_.visibility].clone(), | ||
161 | }) | ||
154 | } | 162 | } |
155 | 163 | ||
156 | pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { | 164 | pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 97cdbbb9e..7b41b148c 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -9,6 +9,7 @@ use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; | |||
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use la_arena::ArenaMap; | 10 | use la_arena::ArenaMap; |
11 | use mbe::ast_to_token_tree; | 11 | use mbe::ast_to_token_tree; |
12 | use smallvec::{smallvec, SmallVec}; | ||
12 | use syntax::{ | 13 | use syntax::{ |
13 | ast::{self, AstNode, AttrsOwner}, | 14 | ast::{self, AstNode, AttrsOwner}, |
14 | match_ast, AstToken, SmolStr, SyntaxNode, | 15 | match_ast, AstToken, SmolStr, SyntaxNode, |
@@ -134,53 +135,42 @@ impl RawAttrs { | |||
134 | let crate_graph = db.crate_graph(); | 135 | let crate_graph = db.crate_graph(); |
135 | let new_attrs = self | 136 | let new_attrs = self |
136 | .iter() | 137 | .iter() |
137 | .filter_map(|attr| { | 138 | .flat_map(|attr| -> SmallVec<[_; 1]> { |
138 | let attr = attr.clone(); | 139 | let attr = attr.clone(); |
139 | let is_cfg_attr = | 140 | let is_cfg_attr = |
140 | attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]); | 141 | attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]); |
141 | if !is_cfg_attr { | 142 | if !is_cfg_attr { |
142 | return Some(attr); | 143 | return smallvec![attr]; |
143 | } | 144 | } |
144 | 145 | ||
145 | let subtree = match &attr.input { | 146 | let subtree = match &attr.input { |
146 | Some(AttrInput::TokenTree(it)) => it, | 147 | Some(AttrInput::TokenTree(it)) => it, |
147 | _ => return Some(attr), | 148 | _ => return smallvec![attr], |
148 | }; | 149 | }; |
149 | 150 | ||
150 | // Input subtree is: `(cfg, attr)` | 151 | // Input subtree is: `(cfg, $(attr),+)` |
151 | // Split it up into a `cfg` and an `attr` subtree. | 152 | // Split it up into a `cfg` subtree and the `attr` subtrees. |
152 | // FIXME: There should be a common API for this. | 153 | // FIXME: There should be a common API for this. |
153 | let mut saw_comma = false; | 154 | let mut parts = subtree.token_trees.split( |
154 | let (mut cfg, attr): (Vec<_>, Vec<_>) = | 155 | |tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','), |
155 | subtree.clone().token_trees.into_iter().partition(|tree| { | 156 | ); |
156 | if saw_comma { | 157 | let cfg = parts.next().unwrap(); |
157 | return false; | 158 | let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; |
158 | } | ||
159 | |||
160 | match tree { | ||
161 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
162 | saw_comma = true; | ||
163 | } | ||
164 | _ => {} | ||
165 | } | ||
166 | |||
167 | true | ||
168 | }); | ||
169 | cfg.pop(); // `,` ends up in here | ||
170 | |||
171 | let attr = Subtree { delimiter: None, token_trees: attr }; | ||
172 | let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg }; | ||
173 | let cfg = CfgExpr::parse(&cfg); | 159 | let cfg = CfgExpr::parse(&cfg); |
160 | let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { | ||
161 | let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; | ||
162 | let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; | ||
163 | let hygiene = Hygiene::new_unhygienic(); // FIXME | ||
164 | Attr::from_src(attr, &hygiene) | ||
165 | }); | ||
174 | 166 | ||
175 | let cfg_options = &crate_graph[krate].cfg_options; | 167 | let cfg_options = &crate_graph[krate].cfg_options; |
176 | if cfg_options.check(&cfg) == Some(false) { | 168 | if cfg_options.check(&cfg) == Some(false) { |
177 | None | 169 | smallvec![] |
178 | } else { | 170 | } else { |
179 | cov_mark::hit!(cfg_attr_active); | 171 | cov_mark::hit!(cfg_attr_active); |
180 | 172 | ||
181 | let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?; | 173 | attrs.collect() |
182 | let hygiene = Hygiene::new_unhygienic(); // FIXME | ||
183 | Attr::from_src(attr, &hygiene) | ||
184 | } | 174 | } |
185 | }) | 175 | }) |
186 | .collect(); | 176 | .collect(); |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 19c4eb521..8bcc350ce 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -253,11 +253,18 @@ pub type LabelSource = InFile<LabelPtr>; | |||
253 | pub struct BodySourceMap { | 253 | pub struct BodySourceMap { |
254 | expr_map: FxHashMap<ExprSource, ExprId>, | 254 | expr_map: FxHashMap<ExprSource, ExprId>, |
255 | expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, | 255 | expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, |
256 | |||
256 | pat_map: FxHashMap<PatSource, PatId>, | 257 | pat_map: FxHashMap<PatSource, PatId>, |
257 | pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, | 258 | pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, |
259 | |||
258 | label_map: FxHashMap<LabelSource, LabelId>, | 260 | label_map: FxHashMap<LabelSource, LabelId>, |
259 | label_map_back: ArenaMap<LabelId, LabelSource>, | 261 | label_map_back: ArenaMap<LabelId, LabelSource>, |
260 | field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>, | 262 | |
263 | /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). | ||
264 | /// Instead, we use id of expression (`92`) to identify the field. | ||
265 | field_map: FxHashMap<InFile<AstPtr<ast::RecordExprField>>, ExprId>, | ||
266 | field_map_back: FxHashMap<ExprId, InFile<AstPtr<ast::RecordExprField>>>, | ||
267 | |||
261 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, | 268 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, |
262 | 269 | ||
263 | /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in | 270 | /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in |
@@ -337,6 +344,8 @@ impl Index<LabelId> for Body { | |||
337 | } | 344 | } |
338 | } | 345 | } |
339 | 346 | ||
347 | // FIXME: Change `node_` prefix to something more reasonable. | ||
348 | // Perhaps `expr_syntax` and `expr_id`? | ||
340 | impl BodySourceMap { | 349 | impl BodySourceMap { |
341 | pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { | 350 | pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { |
342 | self.expr_map_back[expr].clone() | 351 | self.expr_map_back[expr].clone() |
@@ -375,8 +384,12 @@ impl BodySourceMap { | |||
375 | self.label_map.get(&src).cloned() | 384 | self.label_map.get(&src).cloned() |
376 | } | 385 | } |
377 | 386 | ||
378 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> { | 387 | pub fn field_syntax(&self, expr: ExprId) -> InFile<AstPtr<ast::RecordExprField>> { |
379 | self.field_map[&(expr, field)].clone() | 388 | self.field_map_back[&expr].clone() |
389 | } | ||
390 | pub fn node_field(&self, node: InFile<&ast::RecordExprField>) -> Option<ExprId> { | ||
391 | let src = node.map(|it| AstPtr::new(it)); | ||
392 | self.field_map.get(&src).cloned() | ||
380 | } | 393 | } |
381 | 394 | ||
382 | pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) { | 395 | pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 8c8eb8007..7052058f2 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -379,23 +379,22 @@ impl ExprCollector<'_> { | |||
379 | } | 379 | } |
380 | ast::Expr::RecordExpr(e) => { | 380 | ast::Expr::RecordExpr(e) => { |
381 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 381 | let path = e.path().and_then(|path| self.expander.parse_path(path)); |
382 | let mut field_ptrs = Vec::new(); | ||
383 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { | 382 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { |
384 | let fields = nfl | 383 | let fields = nfl |
385 | .fields() | 384 | .fields() |
386 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | ||
387 | .filter_map(|field| { | 385 | .filter_map(|field| { |
388 | self.check_cfg(&field)?; | 386 | self.check_cfg(&field)?; |
389 | 387 | ||
390 | let name = field.field_name()?.as_name(); | 388 | let name = field.field_name()?.as_name(); |
391 | 389 | ||
392 | Some(RecordLitField { | 390 | let expr = match field.expr() { |
393 | name, | 391 | Some(e) => self.collect_expr(e), |
394 | expr: match field.expr() { | 392 | None => self.missing_expr(), |
395 | Some(e) => self.collect_expr(e), | 393 | }; |
396 | None => self.missing_expr(), | 394 | let src = self.expander.to_source(AstPtr::new(&field)); |
397 | }, | 395 | self.source_map.field_map.insert(src.clone(), expr); |
398 | }) | 396 | self.source_map.field_map_back.insert(expr, src); |
397 | Some(RecordLitField { name, expr }) | ||
399 | }) | 398 | }) |
400 | .collect(); | 399 | .collect(); |
401 | let spread = nfl.spread().map(|s| self.collect_expr(s)); | 400 | let spread = nfl.spread().map(|s| self.collect_expr(s)); |
@@ -404,12 +403,7 @@ impl ExprCollector<'_> { | |||
404 | Expr::RecordLit { path, fields: Vec::new(), spread: None } | 403 | Expr::RecordLit { path, fields: Vec::new(), spread: None } |
405 | }; | 404 | }; |
406 | 405 | ||
407 | let res = self.alloc_expr(record_lit, syntax_ptr); | 406 | self.alloc_expr(record_lit, syntax_ptr) |
408 | for (i, ptr) in field_ptrs.into_iter().enumerate() { | ||
409 | let src = self.expander.to_source(ptr); | ||
410 | self.source_map.field_map.insert((res, i), src); | ||
411 | } | ||
412 | res | ||
413 | } | 407 | } |
414 | ast::Expr::FieldExpr(e) => { | 408 | ast::Expr::FieldExpr(e) => { |
415 | let expr = self.collect_expr_opt(e.expr()); | 409 | let expr = self.collect_expr_opt(e.expr()); |
@@ -525,7 +519,7 @@ impl ExprCollector<'_> { | |||
525 | } | 519 | } |
526 | ast::Expr::MacroCall(e) => { | 520 | ast::Expr::MacroCall(e) => { |
527 | let mut ids = vec![]; | 521 | let mut ids = vec![]; |
528 | self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| { | 522 | self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| { |
529 | ids.push(match expansion { | 523 | ids.push(match expansion { |
530 | Some(it) => this.collect_expr(it), | 524 | Some(it) => this.collect_expr(it), |
531 | None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), | 525 | None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), |
@@ -533,6 +527,17 @@ impl ExprCollector<'_> { | |||
533 | }); | 527 | }); |
534 | ids[0] | 528 | ids[0] |
535 | } | 529 | } |
530 | ast::Expr::MacroStmts(e) => { | ||
531 | // FIXME: these statements should be held by some hir containter | ||
532 | for stmt in e.statements() { | ||
533 | self.collect_stmt(stmt); | ||
534 | } | ||
535 | if let Some(expr) = e.expr() { | ||
536 | self.collect_expr(expr) | ||
537 | } else { | ||
538 | self.alloc_expr(Expr::Missing, syntax_ptr) | ||
539 | } | ||
540 | } | ||
536 | } | 541 | } |
537 | } | 542 | } |
538 | 543 | ||
@@ -540,6 +545,7 @@ impl ExprCollector<'_> { | |||
540 | &mut self, | 545 | &mut self, |
541 | e: ast::MacroCall, | 546 | e: ast::MacroCall, |
542 | syntax_ptr: AstPtr<ast::Expr>, | 547 | syntax_ptr: AstPtr<ast::Expr>, |
548 | is_error_recoverable: bool, | ||
543 | mut collector: F, | 549 | mut collector: F, |
544 | ) { | 550 | ) { |
545 | // File containing the macro call. Expansion errors will be attached here. | 551 | // File containing the macro call. Expansion errors will be attached here. |
@@ -573,7 +579,7 @@ impl ExprCollector<'_> { | |||
573 | Some((mark, expansion)) => { | 579 | Some((mark, expansion)) => { |
574 | // FIXME: Statements are too complicated to recover from error for now. | 580 | // FIXME: Statements are too complicated to recover from error for now. |
575 | // It is because we don't have any hygiene for local variable expansion right now. | 581 | // It is because we don't have any hygiene for local variable expansion right now. |
576 | if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { | 582 | if !is_error_recoverable && res.err.is_some() { |
577 | self.expander.exit(self.db, mark); | 583 | self.expander.exit(self.db, mark); |
578 | collector(self, None); | 584 | collector(self, None); |
579 | } else { | 585 | } else { |
@@ -597,56 +603,55 @@ impl ExprCollector<'_> { | |||
597 | } | 603 | } |
598 | 604 | ||
599 | fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { | 605 | fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { |
600 | let stmt = | 606 | let stmt = match s { |
601 | match s { | 607 | ast::Stmt::LetStmt(stmt) => { |
602 | ast::Stmt::LetStmt(stmt) => { | 608 | self.check_cfg(&stmt)?; |
603 | self.check_cfg(&stmt)?; | 609 | |
604 | 610 | let pat = self.collect_pat_opt(stmt.pat()); | |
605 | let pat = self.collect_pat_opt(stmt.pat()); | 611 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); |
606 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 612 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
607 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 613 | vec![Statement::Let { pat, type_ref, initializer }] |
608 | vec![Statement::Let { pat, type_ref, initializer }] | 614 | } |
609 | } | 615 | ast::Stmt::ExprStmt(stmt) => { |
610 | ast::Stmt::ExprStmt(stmt) => { | 616 | self.check_cfg(&stmt)?; |
611 | self.check_cfg(&stmt)?; | 617 | |
612 | 618 | // Note that macro could be expended to multiple statements | |
613 | // Note that macro could be expended to multiple statements | 619 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
614 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 620 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); |
615 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); | 621 | let mut stmts = vec![]; |
616 | let mut stmts = vec![]; | 622 | |
617 | 623 | self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { | |
618 | self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| { | 624 | match expansion { |
619 | match expansion { | 625 | Some(expansion) => { |
620 | Some(expansion) => { | 626 | let statements: ast::MacroStmts = expansion; |
621 | let statements: ast::MacroStmts = expansion; | 627 | |
622 | 628 | statements.statements().for_each(|stmt| { | |
623 | statements.statements().for_each(|stmt| { | 629 | if let Some(mut r) = this.collect_stmt(stmt) { |
624 | if let Some(mut r) = this.collect_stmt(stmt) { | 630 | stmts.append(&mut r); |
625 | stmts.append(&mut r); | ||
626 | } | ||
627 | }); | ||
628 | if let Some(expr) = statements.expr() { | ||
629 | stmts.push(Statement::Expr(this.collect_expr(expr))); | ||
630 | } | 631 | } |
631 | } | 632 | }); |
632 | None => { | 633 | if let Some(expr) = statements.expr() { |
633 | stmts.push(Statement::Expr( | 634 | stmts.push(Statement::Expr(this.collect_expr(expr))); |
634 | this.alloc_expr(Expr::Missing, syntax_ptr.clone()), | ||
635 | )); | ||
636 | } | 635 | } |
637 | } | 636 | } |
638 | }); | 637 | None => { |
639 | stmts | 638 | stmts.push(Statement::Expr( |
640 | } else { | 639 | this.alloc_expr(Expr::Missing, syntax_ptr.clone()), |
641 | vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] | 640 | )); |
642 | } | 641 | } |
642 | } | ||
643 | }); | ||
644 | stmts | ||
645 | } else { | ||
646 | vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] | ||
643 | } | 647 | } |
644 | ast::Stmt::Item(item) => { | 648 | } |
645 | self.check_cfg(&item)?; | 649 | ast::Stmt::Item(item) => { |
650 | self.check_cfg(&item)?; | ||
646 | 651 | ||
647 | return None; | 652 | return None; |
648 | } | 653 | } |
649 | }; | 654 | }; |
650 | 655 | ||
651 | Some(stmt) | 656 | Some(stmt) |
652 | } | 657 | } |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index aea53d527..74a2194e5 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -9,7 +9,7 @@ use crate::{ | |||
9 | attr::Attrs, | 9 | attr::Attrs, |
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | item_tree::{AssocItem, ItemTreeId, ModItem}, | 12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem}, |
13 | type_ref::{TypeBound, TypeRef}, | 13 | type_ref::{TypeBound, TypeRef}, |
14 | visibility::RawVisibility, | 14 | visibility::RawVisibility, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -26,9 +26,9 @@ pub struct FunctionData { | |||
26 | /// can be called as a method. | 26 | /// can be called as a method. |
27 | pub has_self_param: bool, | 27 | pub has_self_param: bool, |
28 | pub has_body: bool, | 28 | pub has_body: bool, |
29 | pub is_unsafe: bool, | 29 | pub qualifier: FunctionQualifier, |
30 | pub is_in_extern_block: bool, | ||
30 | pub is_varargs: bool, | 31 | pub is_varargs: bool, |
31 | pub is_extern: bool, | ||
32 | pub visibility: RawVisibility, | 32 | pub visibility: RawVisibility, |
33 | } | 33 | } |
34 | 34 | ||
@@ -46,9 +46,9 @@ impl FunctionData { | |||
46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
47 | has_self_param: func.has_self_param, | 47 | has_self_param: func.has_self_param, |
48 | has_body: func.has_body, | 48 | has_body: func.has_body, |
49 | is_unsafe: func.is_unsafe, | 49 | qualifier: func.qualifier.clone(), |
50 | is_in_extern_block: func.is_in_extern_block, | ||
50 | is_varargs: func.is_varargs, | 51 | is_varargs: func.is_varargs, |
51 | is_extern: func.is_extern, | ||
52 | visibility: item_tree[func.visibility].clone(), | 52 | visibility: item_tree[func.visibility].clone(), |
53 | }) | 53 | }) |
54 | } | 54 | } |
@@ -87,7 +87,10 @@ impl TypeAliasData { | |||
87 | pub struct TraitData { | 87 | pub struct TraitData { |
88 | pub name: Name, | 88 | pub name: Name, |
89 | pub items: Vec<(Name, AssocItemId)>, | 89 | pub items: Vec<(Name, AssocItemId)>, |
90 | pub auto: bool, | 90 | pub is_auto: bool, |
91 | pub is_unsafe: bool, | ||
92 | pub visibility: RawVisibility, | ||
93 | pub bounds: Box<[TypeBound]>, | ||
91 | } | 94 | } |
92 | 95 | ||
93 | impl TraitData { | 96 | impl TraitData { |
@@ -96,10 +99,13 @@ impl TraitData { | |||
96 | let item_tree = db.item_tree(tr_loc.id.file_id); | 99 | let item_tree = db.item_tree(tr_loc.id.file_id); |
97 | let tr_def = &item_tree[tr_loc.id.value]; | 100 | let tr_def = &item_tree[tr_loc.id.value]; |
98 | let name = tr_def.name.clone(); | 101 | let name = tr_def.name.clone(); |
99 | let auto = tr_def.auto; | 102 | let is_auto = tr_def.is_auto; |
103 | let is_unsafe = tr_def.is_unsafe; | ||
100 | let module_id = tr_loc.container; | 104 | let module_id = tr_loc.container; |
101 | let container = AssocContainerId::TraitId(tr); | 105 | let container = AssocContainerId::TraitId(tr); |
102 | let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); | 106 | let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); |
107 | let visibility = item_tree[tr_def.visibility].clone(); | ||
108 | let bounds = tr_def.bounds.clone(); | ||
103 | 109 | ||
104 | let items = collect_items( | 110 | let items = collect_items( |
105 | db, | 111 | db, |
@@ -111,7 +117,7 @@ impl TraitData { | |||
111 | 100, | 117 | 100, |
112 | ); | 118 | ); |
113 | 119 | ||
114 | Arc::new(TraitData { name, items, auto }) | 120 | Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility, bounds }) |
115 | } | 121 | } |
116 | 122 | ||
117 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { | 123 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { |
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index ac7474f63..7188bb299 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -97,7 +97,7 @@ impl Diagnostic for UnresolvedImport { | |||
97 | 97 | ||
98 | // Diagnostic: unresolved-macro-call | 98 | // Diagnostic: unresolved-macro-call |
99 | // | 99 | // |
100 | // This diagnostic is triggered if rust-analyzer is unable to resolove path to a | 100 | // This diagnostic is triggered if rust-analyzer is unable to resolve the path to a |
101 | // macro in a macro invocation. | 101 | // macro in a macro invocation. |
102 | #[derive(Debug)] | 102 | #[derive(Debug)] |
103 | pub struct UnresolvedMacroCall { | 103 | pub struct UnresolvedMacroCall { |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 6bb334573..7bb22c4c4 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SmolStr, SyntaxKind}; |
28 | 28 | ||
29 | use crate::{ | 29 | use crate::{ |
30 | attr::{Attrs, RawAttrs}, | 30 | attr::{Attrs, RawAttrs}, |
@@ -110,6 +110,11 @@ impl ItemTree { | |||
110 | // still need to collect inner items. | 110 | // still need to collect inner items. |
111 | ctx.lower_inner_items(e.syntax()) | 111 | ctx.lower_inner_items(e.syntax()) |
112 | }, | 112 | }, |
113 | ast::ExprStmt(stmt) => { | ||
114 | // Macros can expand to stmt. We return an empty item tree in this case, but | ||
115 | // still need to collect inner items. | ||
116 | ctx.lower_inner_items(stmt.syntax()) | ||
117 | }, | ||
113 | _ => { | 118 | _ => { |
114 | panic!("cannot create item tree from {:?} {}", syntax, syntax); | 119 | panic!("cannot create item tree from {:?} {}", syntax, syntax); |
115 | }, | 120 | }, |
@@ -209,18 +214,6 @@ impl ItemTree { | |||
209 | } | 214 | } |
210 | } | 215 | } |
211 | 216 | ||
212 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { | ||
213 | // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty | ||
214 | // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with). | ||
215 | let root = | ||
216 | db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree"); | ||
217 | |||
218 | let id = self[of.value].ast_id(); | ||
219 | let map = db.ast_id_map(of.file_id); | ||
220 | let ptr = map.get(id); | ||
221 | ptr.to_node(&root) | ||
222 | } | ||
223 | |||
224 | fn data(&self) -> &ItemTreeData { | 217 | fn data(&self) -> &ItemTreeData { |
225 | self.data.as_ref().expect("attempted to access data of empty ItemTree") | 218 | self.data.as_ref().expect("attempted to access data of empty ItemTree") |
226 | } | 219 | } |
@@ -563,16 +556,25 @@ pub struct Function { | |||
563 | pub generic_params: GenericParamsId, | 556 | pub generic_params: GenericParamsId, |
564 | pub has_self_param: bool, | 557 | pub has_self_param: bool, |
565 | pub has_body: bool, | 558 | pub has_body: bool, |
566 | pub is_unsafe: bool, | 559 | pub qualifier: FunctionQualifier, |
567 | /// Whether the function is located in an `extern` block (*not* whether it is an | 560 | /// Whether the function is located in an `extern` block (*not* whether it is an |
568 | /// `extern "abi" fn`). | 561 | /// `extern "abi" fn`). |
569 | pub is_extern: bool, | 562 | pub is_in_extern_block: bool, |
570 | pub params: Box<[Idx<TypeRef>]>, | 563 | pub params: Box<[Idx<TypeRef>]>, |
571 | pub is_varargs: bool, | 564 | pub is_varargs: bool, |
572 | pub ret_type: Idx<TypeRef>, | 565 | pub ret_type: Idx<TypeRef>, |
573 | pub ast_id: FileAstId<ast::Fn>, | 566 | pub ast_id: FileAstId<ast::Fn>, |
574 | } | 567 | } |
575 | 568 | ||
569 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
570 | pub struct FunctionQualifier { | ||
571 | pub is_default: bool, | ||
572 | pub is_const: bool, | ||
573 | pub is_async: bool, | ||
574 | pub is_unsafe: bool, | ||
575 | pub abi: Option<SmolStr>, | ||
576 | } | ||
577 | |||
576 | #[derive(Debug, Clone, Eq, PartialEq)] | 578 | #[derive(Debug, Clone, Eq, PartialEq)] |
577 | pub struct Struct { | 579 | pub struct Struct { |
578 | pub name: Name, | 580 | pub name: Name, |
@@ -636,7 +638,9 @@ pub struct Trait { | |||
636 | pub name: Name, | 638 | pub name: Name, |
637 | pub visibility: RawVisibilityId, | 639 | pub visibility: RawVisibilityId, |
638 | pub generic_params: GenericParamsId, | 640 | pub generic_params: GenericParamsId, |
639 | pub auto: bool, | 641 | pub is_auto: bool, |
642 | pub is_unsafe: bool, | ||
643 | pub bounds: Box<[TypeBound]>, | ||
640 | pub items: Box<[AssocItem]>, | 644 | pub items: Box<[AssocItem]>, |
641 | pub ast_id: FileAstId<ast::Trait>, | 645 | pub ast_id: FileAstId<ast::Trait>, |
642 | } | 646 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 240fdacf9..7e91b991d 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -391,14 +391,33 @@ impl Ctx { | |||
391 | let has_body = func.body().is_some(); | 391 | let has_body = func.body().is_some(); |
392 | 392 | ||
393 | let ast_id = self.source_ast_id_map.ast_id(func); | 393 | let ast_id = self.source_ast_id_map.ast_id(func); |
394 | let qualifier = FunctionQualifier { | ||
395 | is_default: func.default_token().is_some(), | ||
396 | is_const: func.const_token().is_some(), | ||
397 | is_async: func.async_token().is_some(), | ||
398 | is_unsafe: func.unsafe_token().is_some(), | ||
399 | abi: func.abi().map(|abi| { | ||
400 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | ||
401 | match abi.syntax().last_token() { | ||
402 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | ||
403 | // FIXME: Better way to unescape? | ||
404 | tok.text().trim_matches('"').into() | ||
405 | } | ||
406 | _ => { | ||
407 | // `extern` default to be `extern "C"`. | ||
408 | "C".into() | ||
409 | } | ||
410 | } | ||
411 | }), | ||
412 | }; | ||
394 | let mut res = Function { | 413 | let mut res = Function { |
395 | name, | 414 | name, |
396 | visibility, | 415 | visibility, |
397 | generic_params: GenericParamsId::EMPTY, | 416 | generic_params: GenericParamsId::EMPTY, |
398 | has_self_param, | 417 | has_self_param, |
399 | has_body, | 418 | has_body, |
400 | is_unsafe: func.unsafe_token().is_some(), | 419 | qualifier, |
401 | is_extern: false, | 420 | is_in_extern_block: false, |
402 | params, | 421 | params, |
403 | is_varargs, | 422 | is_varargs, |
404 | ret_type, | 423 | ret_type, |
@@ -481,7 +500,9 @@ impl Ctx { | |||
481 | let visibility = self.lower_visibility(trait_def); | 500 | let visibility = self.lower_visibility(trait_def); |
482 | let generic_params = | 501 | let generic_params = |
483 | self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); | 502 | self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); |
484 | let auto = trait_def.auto_token().is_some(); | 503 | let is_auto = trait_def.auto_token().is_some(); |
504 | let is_unsafe = trait_def.unsafe_token().is_some(); | ||
505 | let bounds = self.lower_type_bounds(trait_def); | ||
485 | let items = trait_def.assoc_item_list().map(|list| { | 506 | let items = trait_def.assoc_item_list().map(|list| { |
486 | self.with_inherited_visibility(visibility, |this| { | 507 | self.with_inherited_visibility(visibility, |this| { |
487 | list.assoc_items() | 508 | list.assoc_items() |
@@ -501,7 +522,9 @@ impl Ctx { | |||
501 | name, | 522 | name, |
502 | visibility, | 523 | visibility, |
503 | generic_params, | 524 | generic_params, |
504 | auto, | 525 | is_auto, |
526 | is_unsafe, | ||
527 | bounds: bounds.into(), | ||
505 | items: items.unwrap_or_default(), | 528 | items: items.unwrap_or_default(), |
506 | ast_id, | 529 | ast_id, |
507 | }; | 530 | }; |
@@ -608,8 +631,8 @@ impl Ctx { | |||
608 | ast::ExternItem::Fn(ast) => { | 631 | ast::ExternItem::Fn(ast) => { |
609 | let func_id = self.lower_function(&ast)?; | 632 | let func_id = self.lower_function(&ast)?; |
610 | let func = &mut self.data().functions[func_id.index]; | 633 | let func = &mut self.data().functions[func_id.index]; |
611 | func.is_unsafe = is_intrinsic_fn_unsafe(&func.name); | 634 | func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); |
612 | func.is_extern = true; | 635 | func.is_in_extern_block = true; |
613 | func_id.into() | 636 | func_id.into() |
614 | } | 637 | } |
615 | ast::ExternItem::Static(ast) => { | 638 | ast::ExternItem::Static(ast) => { |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 6d11c5be4..c6655c5fb 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -341,6 +341,16 @@ pub enum DefWithBodyId { | |||
341 | 341 | ||
342 | impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); | 342 | impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); |
343 | 343 | ||
344 | impl DefWithBodyId { | ||
345 | pub fn as_generic_def_id(self) -> Option<GenericDefId> { | ||
346 | match self { | ||
347 | DefWithBodyId::FunctionId(f) => Some(f.into()), | ||
348 | DefWithBodyId::StaticId(_) => None, | ||
349 | DefWithBodyId::ConstId(c) => Some(c.into()), | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
344 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 354 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
345 | pub enum AssocItemId { | 355 | pub enum AssocItemId { |
346 | FunctionId(FunctionId), | 356 | FunctionId(FunctionId), |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 9ed48c506..81cf652b0 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 16 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -1455,7 +1455,8 @@ impl ModCollector<'_, '_> { | |||
1455 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1455 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
1456 | 1456 | ||
1457 | // Case 1: try to resolve in legacy scope and expand macro_rules | 1457 | // Case 1: try to resolve in legacy scope and expand macro_rules |
1458 | if let Ok(Ok(macro_call_id)) = macro_call_as_call_id( | 1458 | let mut error = None; |
1459 | match macro_call_as_call_id( | ||
1459 | &ast_id, | 1460 | &ast_id, |
1460 | self.def_collector.db, | 1461 | self.def_collector.db, |
1461 | self.def_collector.def_map.krate, | 1462 | self.def_collector.def_map.krate, |
@@ -1468,16 +1469,28 @@ impl ModCollector<'_, '_> { | |||
1468 | ) | 1469 | ) |
1469 | }) | 1470 | }) |
1470 | }, | 1471 | }, |
1471 | &mut |_err| (), | 1472 | &mut |err| error = Some(err), |
1472 | ) { | 1473 | ) { |
1473 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1474 | Ok(Ok(macro_call_id)) => { |
1474 | module_id: self.module_id, | 1475 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1475 | ast_id, | 1476 | module_id: self.module_id, |
1476 | legacy: Some(macro_call_id), | 1477 | ast_id, |
1477 | depth: self.macro_depth + 1, | 1478 | legacy: Some(macro_call_id), |
1478 | }); | 1479 | depth: self.macro_depth + 1, |
1480 | }); | ||
1479 | 1481 | ||
1480 | return; | 1482 | return; |
1483 | } | ||
1484 | Ok(Err(_)) => { | ||
1485 | // Built-in macro failed eager expansion. | ||
1486 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( | ||
1487 | self.module_id, | ||
1488 | MacroCallKind::FnLike(ast_id.ast_id), | ||
1489 | error.unwrap().to_string(), | ||
1490 | )); | ||
1491 | return; | ||
1492 | } | ||
1493 | Err(UnresolvedMacro) => (), | ||
1481 | } | 1494 | } |
1482 | 1495 | ||
1483 | // Case 2: resolve in module scope, expand during name resolution. | 1496 | // Case 2: resolve in module scope, expand during name resolution. |
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs index d5ef8ceb5..c22ef46fd 100644 --- a/crates/hir_def/src/nameres/tests/diagnostics.rs +++ b/crates/hir_def/src/nameres/tests/diagnostics.rs | |||
@@ -149,6 +149,54 @@ fn inactive_via_cfg_attr() { | |||
149 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} | 149 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} |
150 | 150 | ||
151 | #[cfg_attr(never, cfg(no))] fn g() {} | 151 | #[cfg_attr(never, cfg(no))] fn g() {} |
152 | |||
153 | #[cfg_attr(not(never), inline, cfg(no))] fn h() {} | ||
154 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
155 | "#, | ||
156 | ); | ||
157 | } | ||
158 | |||
159 | #[test] | ||
160 | fn unresolved_legacy_scope_macro() { | ||
161 | check_diagnostics( | ||
162 | r#" | ||
163 | //- /lib.rs | ||
164 | macro_rules! m { () => {} } | ||
165 | |||
166 | m!(); | ||
167 | m2!(); | ||
168 | //^^^^^^ unresolved macro call | ||
169 | "#, | ||
170 | ); | ||
171 | } | ||
172 | |||
173 | #[test] | ||
174 | fn unresolved_module_scope_macro() { | ||
175 | check_diagnostics( | ||
176 | r#" | ||
177 | //- /lib.rs | ||
178 | mod mac { | ||
179 | #[macro_export] | ||
180 | macro_rules! m { () => {} } | ||
181 | } | ||
182 | |||
183 | self::m!(); | ||
184 | self::m2!(); | ||
185 | //^^^^^^^^^^^^ unresolved macro call | ||
186 | "#, | ||
187 | ); | ||
188 | } | ||
189 | |||
190 | #[test] | ||
191 | fn builtin_macro_fails_expansion() { | ||
192 | check_diagnostics( | ||
193 | r#" | ||
194 | //- /lib.rs | ||
195 | #[rustc_builtin_macro] | ||
196 | macro_rules! include { () => {} } | ||
197 | |||
198 | include!("doesntexist"); | ||
199 | //^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens | ||
152 | "#, | 200 | "#, |
153 | ); | 201 | ); |
154 | } | 202 | } |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 0e60dc2b6..8c923bb7b 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -9,7 +9,10 @@ use std::{ | |||
9 | 9 | ||
10 | use crate::{body::LowerCtx, type_ref::LifetimeRef}; | 10 | use crate::{body::LowerCtx, type_ref::LifetimeRef}; |
11 | use base_db::CrateId; | 11 | use base_db::CrateId; |
12 | use hir_expand::{hygiene::Hygiene, name::Name}; | 12 | use hir_expand::{ |
13 | hygiene::Hygiene, | ||
14 | name::{name, Name}, | ||
15 | }; | ||
13 | use syntax::ast; | 16 | use syntax::ast; |
14 | 17 | ||
15 | use crate::{ | 18 | use crate::{ |
@@ -209,6 +212,12 @@ impl Path { | |||
209 | }; | 212 | }; |
210 | Some(res) | 213 | Some(res) |
211 | } | 214 | } |
215 | |||
216 | pub fn is_self_type(&self) -> bool { | ||
217 | self.type_anchor.is_none() | ||
218 | && self.generic_args == &[None] | ||
219 | && self.mod_path.as_ident() == Some(&name!(Self)) | ||
220 | } | ||
212 | } | 221 | } |
213 | 222 | ||
214 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 223 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index eda982c85..10977761c 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet; | |||
15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; | 15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; |
16 | use test_utils::extract_annotations; | 16 | use test_utils::extract_annotations; |
17 | 17 | ||
18 | use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; | 18 | use crate::{db::DefDatabase, nameres::DefMap, src::HasSource, Lookup, ModuleDefId, ModuleId}; |
19 | 19 | ||
20 | #[salsa::database( | 20 | #[salsa::database( |
21 | base_db::SourceDatabaseExtStorage, | 21 | base_db::SourceDatabaseExtStorage, |
@@ -115,14 +115,9 @@ impl TestDB { | |||
115 | if file_id != position.file_id.into() { | 115 | if file_id != position.file_id.into() { |
116 | continue; | 116 | continue; |
117 | } | 117 | } |
118 | let root = self.parse_or_expand(file_id).unwrap(); | ||
119 | let ast_map = self.ast_id_map(file_id); | ||
120 | let item_tree = self.item_tree(file_id); | ||
121 | for decl in module.scope.declarations() { | 118 | for decl in module.scope.declarations() { |
122 | if let ModuleDefId::FunctionId(it) = decl { | 119 | if let ModuleDefId::FunctionId(it) = decl { |
123 | let ast = | 120 | let range = it.lookup(self).source(self).value.syntax().text_range(); |
124 | ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root); | ||
125 | let range = ast.syntax().text_range(); | ||
126 | 121 | ||
127 | if !range.contains(position.offset) { | 122 | if !range.contains(position.offset) { |
128 | continue; | 123 | continue; |