aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-10-29 08:15:51 +0000
committerAleksey Kladov <[email protected]>2019-10-29 08:15:51 +0000
commit77f90caf2deeb6a2d2c8196399fbba61bf0c461d (patch)
tree09667ecbdcc8b84916c509d3a3d09ab56b5d4aed /crates/ra_hir/src
parent120000609ab0a0e6a946404d0477f5a0a7107800 (diff)
start ra_hir_def crate
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/expr/lower.rs11
-rw-r--r--crates/ra_hir/src/from_source.rs4
-rw-r--r--crates/ra_hir/src/ids.rs2
-rw-r--r--crates/ra_hir/src/impl_block.rs4
-rw-r--r--crates/ra_hir/src/nameres/collector.rs13
-rw-r--r--crates/ra_hir/src/source_id.rs132
7 files changed, 39 insertions, 131 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 489a3b19c..7abbf8dca 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -59,11 +59,11 @@ pub trait InternDatabase: SourceDatabase {
59/// incremental. 59/// incremental.
60#[salsa::query_group(AstDatabaseStorage)] 60#[salsa::query_group(AstDatabaseStorage)]
61pub trait AstDatabase: InternDatabase { 61pub trait AstDatabase: InternDatabase {
62 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] 62 #[salsa::invoke(crate::source_id::ast_id_map_query)]
63 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; 63 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
64 64
65 #[salsa::transparent] 65 #[salsa::transparent]
66 #[salsa::invoke(crate::source_id::AstIdMap::file_item_query)] 66 #[salsa::invoke(crate::source_id::file_item_query)]
67 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> SyntaxNode; 67 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> SyntaxNode;
68 68
69 #[salsa::transparent] 69 #[salsa::transparent]
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index 50ea429ea..24733b3de 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -16,7 +16,7 @@ use crate::{
16 path::GenericArgs, 16 path::GenericArgs,
17 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, 17 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
18 type_ref::TypeRef, 18 type_ref::TypeRef,
19 DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path, Resolver, 19 AstId, DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path, Resolver,
20 Source, 20 Source,
21}; 21};
22 22
@@ -458,11 +458,10 @@ where
458 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 458 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
459 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 459 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
460 ast::Expr::MacroCall(e) => { 460 ast::Expr::MacroCall(e) => {
461 let ast_id = self 461 let ast_id = AstId::new(
462 .db 462 self.current_file_id,
463 .ast_id_map(self.current_file_id) 463 self.db.ast_id_map(self.current_file_id).ast_id(&e),
464 .ast_id(&e) 464 );
465 .with_file_id(self.current_file_id);
466 465
467 if let Some(path) = e.path().and_then(|path| self.parse_path(path)) { 466 if let Some(path) = e.path().and_then(|path| self.parse_path(path)) {
468 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { 467 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index f80d8eb5f..7954c04b2 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -11,7 +11,7 @@ use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx}, 12 ids::{AstItemDef, LocationCtx},
13 name::AsName, 13 name::AsName,
14 Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module, 14 AstId, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module,
15 ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, 15 ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef,
16}; 16};
17 17
@@ -183,7 +183,7 @@ impl Module {
183 ModuleSource::Module(ref module) => { 183 ModuleSource::Module(ref module) => {
184 assert!(!module.has_semi()); 184 assert!(!module.has_semi());
185 let ast_id_map = db.ast_id_map(src.file_id); 185 let ast_id_map = db.ast_id_map(src.file_id);
186 let item_id = ast_id_map.ast_id(module).with_file_id(src.file_id); 186 let item_id = AstId::new(src.file_id, ast_id_map.ast_id(module));
187 Some(item_id) 187 Some(item_id)
188 } 188 }
189 ModuleSource::SourceFile(_) => None, 189 ModuleSource::SourceFile(_) => None,
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 518ea32e9..f141206c6 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -264,7 +264,7 @@ pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
264 Self::from_ast_id(ctx, item_id) 264 Self::from_ast_id(ctx, item_id)
265 } 265 }
266 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self { 266 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self {
267 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) }; 267 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) };
268 Self::intern(ctx.db, loc) 268 Self::intern(ctx.db, loc)
269 } 269 }
270 fn source(self, db: &impl AstDatabase) -> Source<N> { 270 fn source(self, db: &impl AstDatabase) -> Source<N> {
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 33ef87563..9c739f3f1 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -20,7 +20,7 @@ use crate::{
20 resolve::Resolver, 20 resolve::Resolver,
21 ty::Ty, 21 ty::Ty,
22 type_ref::TypeRef, 22 type_ref::TypeRef,
23 AssocItem, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef, 23 AssocItem, AstId, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef,
24 TypeAlias, 24 TypeAlias,
25}; 25};
26 26
@@ -256,7 +256,7 @@ impl ModuleImplBlocks {
256 } 256 }
257 257
258 //FIXME: we should really cut down on the boilerplate required to process a macro 258 //FIXME: we should really cut down on the boilerplate required to process a macro
259 let ast_id = db.ast_id_map(file_id).ast_id(&macro_call).with_file_id(file_id); 259 let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(&macro_call));
260 if let Some(path) = macro_call 260 if let Some(path) = macro_call
261 .path() 261 .path()
262 .and_then(|path| Path::from_src(Source { ast: path, file_id }, db)) 262 .and_then(|path| Path::from_src(Source { ast: path, file_id }, db))
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index b5fe16bfa..4f363df36 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -567,7 +567,7 @@ where
567 // inline module, just recurse 567 // inline module, just recurse
568 raw::ModuleData::Definition { name, items, ast_id } => { 568 raw::ModuleData::Definition { name, items, ast_id } => {
569 let module_id = 569 let module_id =
570 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None); 570 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
571 571
572 ModCollector { 572 ModCollector {
573 def_collector: &mut *self.def_collector, 573 def_collector: &mut *self.def_collector,
@@ -583,7 +583,7 @@ where
583 } 583 }
584 // out of line module, resolve, parse and recurse 584 // out of line module, resolve, parse and recurse
585 raw::ModuleData::Declaration { name, ast_id } => { 585 raw::ModuleData::Declaration { name, ast_id } => {
586 let ast_id = ast_id.with_file_id(self.file_id); 586 let ast_id = AstId::new(self.file_id, *ast_id);
587 match self.mod_dir.resolve_declaration( 587 match self.mod_dir.resolve_declaration(
588 self.def_collector.db, 588 self.def_collector.db,
589 self.file_id, 589 self.file_id,
@@ -671,21 +671,18 @@ where
671 } 671 }
672 672
673 fn collect_macro(&mut self, mac: &raw::MacroData) { 673 fn collect_macro(&mut self, mac: &raw::MacroData) {
674 let ast_id = AstId::new(self.file_id, mac.ast_id);
675
674 // Case 1: macro rules, define a macro in crate-global mutable scope 676 // Case 1: macro rules, define a macro in crate-global mutable scope
675 if is_macro_rules(&mac.path) { 677 if is_macro_rules(&mac.path) {
676 if let Some(name) = &mac.name { 678 if let Some(name) = &mac.name {
677 let macro_id = MacroDefId { 679 let macro_id = MacroDefId { ast_id, krate: self.def_collector.def_map.krate };
678 ast_id: mac.ast_id.with_file_id(self.file_id),
679 krate: self.def_collector.def_map.krate,
680 };
681 let macro_ = MacroDef { id: macro_id }; 680 let macro_ = MacroDef { id: macro_id };
682 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); 681 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
683 } 682 }
684 return; 683 return;
685 } 684 }
686 685
687 let ast_id = mac.ast_id.with_file_id(self.file_id);
688
689 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering 686 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering
690 // recursive item collection. 687 // recursive item collection.
691 if let Some(macro_def) = mac.path.as_ident().and_then(|name| { 688 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
diff --git a/crates/ra_hir/src/source_id.rs b/crates/ra_hir/src/source_id.rs
index a4dd99598..260b79661 100644
--- a/crates/ra_hir/src/source_id.rs
+++ b/crates/ra_hir/src/source_id.rs
@@ -2,18 +2,18 @@
2 2
3use std::{ 3use std::{
4 hash::{Hash, Hasher}, 4 hash::{Hash, Hasher},
5 marker::PhantomData,
6 sync::Arc, 5 sync::Arc,
7}; 6};
8 7
9use ra_arena::{impl_arena_id, Arena, RawId}; 8pub use hir_def::ast_id_map::{AstIdMap, ErasedFileAstId, FileAstId};
10use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxNodePtr}; 9use ra_syntax::{AstNode, SyntaxNode};
11 10
12use crate::{db::AstDatabase, HirFileId}; 11use crate::{db::AstDatabase, HirFileId};
13 12
14/// `AstId` points to an AST node in any file. 13/// `AstId` points to an AST node in any file.
15/// 14///
16/// It is stable across reparses, and can be used as salsa key/value. 15/// It is stable across reparses, and can be used as salsa key/value.
16// FIXME: isn't this just a `Source<FileAstId<N>>` ?
17#[derive(Debug)] 17#[derive(Debug)]
18pub(crate) struct AstId<N: AstNode> { 18pub(crate) struct AstId<N: AstNode> {
19 file_id: HirFileId, 19 file_id: HirFileId,
@@ -40,122 +40,34 @@ impl<N: AstNode> Hash for AstId<N> {
40} 40}
41 41
42impl<N: AstNode> AstId<N> { 42impl<N: AstNode> AstId<N> {
43 pub fn new(file_id: HirFileId, file_ast_id: FileAstId<N>) -> AstId<N> {
44 AstId { file_id, file_ast_id }
45 }
46
43 pub(crate) fn file_id(&self) -> HirFileId { 47 pub(crate) fn file_id(&self) -> HirFileId {
44 self.file_id 48 self.file_id
45 } 49 }
46 50
47 pub(crate) fn to_node(&self, db: &impl AstDatabase) -> N { 51 pub(crate) fn to_node(&self, db: &impl AstDatabase) -> N {
48 let syntax_node = db.ast_id_to_node(self.file_id, self.file_ast_id.raw); 52 let syntax_node = db.ast_id_to_node(self.file_id, self.file_ast_id.into());
49 N::cast(syntax_node).unwrap() 53 N::cast(syntax_node).unwrap()
50 } 54 }
51} 55}
52 56
53/// `AstId` points to an AST node in a specific file. 57pub(crate) fn ast_id_map_query(db: &impl AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
54#[derive(Debug)] 58 let map = if let Some(node) = db.parse_or_expand(file_id) {
55pub(crate) struct FileAstId<N: AstNode> { 59 AstIdMap::from_source(&node)
56 raw: ErasedFileAstId, 60 } else {
57 _ty: PhantomData<fn() -> N>, 61 AstIdMap::default()
58} 62 };
59 63 Arc::new(map)
60impl<N: AstNode> Clone for FileAstId<N> {
61 fn clone(&self) -> FileAstId<N> {
62 *self
63 }
64}
65impl<N: AstNode> Copy for FileAstId<N> {}
66
67impl<N: AstNode> PartialEq for FileAstId<N> {
68 fn eq(&self, other: &Self) -> bool {
69 self.raw == other.raw
70 }
71}
72impl<N: AstNode> Eq for FileAstId<N> {}
73impl<N: AstNode> Hash for FileAstId<N> {
74 fn hash<H: Hasher>(&self, hasher: &mut H) {
75 self.raw.hash(hasher);
76 }
77}
78
79impl<N: AstNode> FileAstId<N> {
80 pub(crate) fn with_file_id(self, file_id: HirFileId) -> AstId<N> {
81 AstId { file_id, file_ast_id: self }
82 }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
86pub struct ErasedFileAstId(RawId);
87impl_arena_id!(ErasedFileAstId);
88
89/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
90#[derive(Debug, PartialEq, Eq, Default)]
91pub struct AstIdMap {
92 arena: Arena<ErasedFileAstId, SyntaxNodePtr>,
93} 64}
94 65
95impl AstIdMap { 66pub(crate) fn file_item_query(
96 pub(crate) fn ast_id_map_query(db: &impl AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { 67 db: &impl AstDatabase,
97 let map = if let Some(node) = db.parse_or_expand(file_id) { 68 file_id: HirFileId,
98 AstIdMap::from_source(&node) 69 ast_id: ErasedFileAstId,
99 } else { 70) -> SyntaxNode {
100 AstIdMap::default() 71 let node = db.parse_or_expand(file_id).unwrap();
101 }; 72 db.ast_id_map(file_id)[ast_id].to_node(&node)
102 Arc::new(map)
103 }
104
105 pub(crate) fn file_item_query(
106 db: &impl AstDatabase,
107 file_id: HirFileId,
108 ast_id: ErasedFileAstId,
109 ) -> SyntaxNode {
110 let node = db.parse_or_expand(file_id).unwrap();
111 db.ast_id_map(file_id).arena[ast_id].to_node(&node)
112 }
113
114 pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {
115 let ptr = SyntaxNodePtr::new(item.syntax());
116 let raw = match self.arena.iter().find(|(_id, i)| **i == ptr) {
117 Some((it, _)) => it,
118 None => panic!(
119 "Can't find {:?} in AstIdMap:\n{:?}",
120 item.syntax(),
121 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
122 ),
123 };
124
125 FileAstId { raw, _ty: PhantomData }
126 }
127
128 fn from_source(node: &SyntaxNode) -> AstIdMap {
129 assert!(node.parent().is_none());
130 let mut res = AstIdMap { arena: Arena::default() };
131 // By walking the tree in bread-first order we make sure that parents
132 // get lower ids then children. That is, adding a new child does not
133 // change parent's id. This means that, say, adding a new function to a
134 // trait does not change ids of top-level items, which helps caching.
135 bfs(node, |it| {
136 if let Some(module_item) = ast::ModuleItem::cast(it.clone()) {
137 res.alloc(module_item.syntax());
138 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
139 res.alloc(macro_call.syntax());
140 }
141 });
142 res
143 }
144
145 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
146 self.arena.alloc(SyntaxNodePtr::new(item))
147 }
148}
149
150/// Walks the subtree in bfs order, calling `f` for each node.
151fn bfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode)) {
152 let mut curr_layer = vec![node.clone()];
153 let mut next_layer = vec![];
154 while !curr_layer.is_empty() {
155 curr_layer.drain(..).for_each(|node| {
156 next_layer.extend(node.children());
157 f(node);
158 });
159 std::mem::swap(&mut curr_layer, &mut next_layer);
160 }
161} 73}