aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/from_source.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-20 13:23:38 +0000
committerGitHub <[email protected]>2019-11-20 13:23:38 +0000
commitb568bcfe6d94d5f4c6cdc012b766473e5b771a26 (patch)
treee54c306ac0512e3610430574dc8bea39e4b50218 /crates/ra_hir/src/from_source.rs
parent2d47f380baad4eacd87331c4b86c0ecb28239499 (diff)
parentcebeedc66fc40097eae20bf1767a285d00269966 (diff)
Merge #2325
2325: Next gen IDs for functions r=matklad a=matklad The current system with AstIds has two primaraly drawbacks: * It is possible to manufacture IDs out of thin air. For example, it's possible to create IDs for items which are not considered in CrateDefMap due to cfg. Or it is possible to mixup structs and unions, because they share ID space. * Getting the ID of a parent requires a secondary index. Instead, the plan is to pursue the more traditional approach, where each items stores the id of the parent declaration. This makes `FromSource` more awkward, but also more correct: now, to get from an AST to HIR, we first do this recursively for the parent item, and the just search the children of the parent for the matching def Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/from_source.rs')
-rw-r--r--crates/ra_hir/src/from_source.rs65
1 files changed, 58 insertions, 7 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index f4dca25cb..303d5f138 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -4,15 +4,15 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 6 ast::{self, AstNode, NameOwner},
7 match_ast, 7 match_ast, AstPtr,
8}; 8};
9 9
10use crate::{ 10use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx}, 12 ids::{AstItemDef, LocationCtx},
13 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, 13 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource,
14 Local, MacroDef, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, 14 ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct,
15 Union, VariantDef, 15 StructField, Trait, TypeAlias, Union, VariantDef,
16}; 16};
17 17
18pub trait FromSource: Sized { 18pub trait FromSource: Sized {
@@ -52,10 +52,51 @@ impl FromSource for Trait {
52impl FromSource for Function { 52impl FromSource for Function {
53 type Ast = ast::FnDef; 53 type Ast = ast::FnDef;
54 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 54 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
55 let id = from_source(db, src)?; 55 // FIXME: this doesn't try to handle nested declarations
56 Some(Function { id }) 56 for container in src.value.syntax().ancestors() {
57 let res = match_ast! {
58 match container {
59 ast::TraitDef(it) => {
60 let c = Trait::from_source(db, src.with_value(it))?;
61 c.items(db)
62 .into_iter()
63 .filter_map(|it| match it {
64 AssocItem::Function(it) => Some(it),
65 _ => None
66 })
67 .find(|it| same_source(&it.source(db), &src))?
68 },
69 ast::ImplBlock(it) => {
70 let c = ImplBlock::from_source(db, src.with_value(it))?;
71 c.items(db)
72 .into_iter()
73 .filter_map(|it| match it {
74 AssocItem::Function(it) => Some(it),
75 _ => None
76 })
77 .find(|it| same_source(&it.source(db), &src))?
78
79 },
80 _ => { continue },
81 }
82 };
83 return Some(res);
84 }
85
86 let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
87 let c = Module::from_definition(db, src.with_value(module_source))?;
88 let res = c
89 .declarations(db)
90 .into_iter()
91 .filter_map(|it| match it {
92 ModuleDef::Function(it) => Some(it),
93 _ => None,
94 })
95 .find(|it| same_source(&it.source(db), &src));
96 res
57 } 97 }
58} 98}
99
59impl FromSource for Const { 100impl FromSource for Const {
60 type Ast = ast::ConstDef; 101 type Ast = ast::ConstDef;
61 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 102 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
@@ -108,7 +149,7 @@ impl FromSource for EnumVariant {
108 let parent_enum = src.value.parent_enum(); 149 let parent_enum = src.value.parent_enum();
109 let src_enum = Source { file_id: src.file_id, value: parent_enum }; 150 let src_enum = Source { file_id: src.file_id, value: parent_enum };
110 let variants = Enum::from_source(db, src_enum)?.variants(db); 151 let variants = Enum::from_source(db, src_enum)?.variants(db);
111 variants.into_iter().find(|v| v.source(db) == src) 152 variants.into_iter().find(|v| same_source(&v.source(db), &src))
112 } 153 }
113} 154}
114 155
@@ -216,3 +257,13 @@ where
216 let ctx = LocationCtx::new(db, module.id, src.file_id); 257 let ctx = LocationCtx::new(db, module.id, src.file_id);
217 Some(DEF::from_ast(ctx, &src.value)) 258 Some(DEF::from_ast(ctx, &src.value))
218} 259}
260
261/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
262/// equal if they point to exactly the same object.
263///
264/// In general, we do not guarantee that we have exactly one instance of a
265/// syntax tree for each file. We probably should add such guanratree, but, for
266/// the time being, we will use identity-less AstPtr comparison.
267fn same_source<N: AstNode>(s1: &Source<N>, s2: &Source<N>) -> bool {
268 s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new)
269}