aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-12-05 14:16:59 +0000
committerAleksey Kladov <[email protected]>2019-12-05 15:55:54 +0000
commit0c0ce1ae418a2f3f4fc125bd701cdb327f607002 (patch)
tree596e533284a136297c8443094434c9738d24c435 /crates/ra_hir/src
parent4c0bd068da39e74c66104206e27c270454e3562e (diff)
Introduce ChildFromSource
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/from_source.rs141
1 files changed, 40 insertions, 101 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 18d87f6d7..58203c721 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,17 +1,20 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use either::Either;
2 3
3use hir_def::{nameres::ModuleSource, AstItemDef, LocationCtx, ModuleId}; 4use hir_def::{
5 child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId,
6 LocationCtx, ModuleId, VariantId,
7};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 8use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 9use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 10 ast::{self, AstNode, NameOwner},
7 match_ast, AstPtr, SyntaxNode, 11 match_ast, SyntaxNode,
8}; 12};
9 13
10use crate::{ 14use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 15 db::{AstDatabase, DefDatabase, HirDatabase},
12 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, 16 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local,
13 InFile, Local, MacroDef, Module, ModuleDef, Static, Struct, StructField, Trait, TypeAlias, 17 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union,
14 Union, VariantDef,
15}; 18};
16 19
17pub trait FromSource: Sized { 20pub trait FromSource: Sized {
@@ -50,98 +53,45 @@ impl FromSource for Trait {
50impl FromSource for Function { 53impl FromSource for Function {
51 type Ast = ast::FnDef; 54 type Ast = ast::FnDef;
52 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 55 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
53 let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { 56 match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
54 Container::Trait(it) => it.items(db), 57 Container::Trait(it) => it.id.child_from_source(db, src),
55 Container::ImplBlock(it) => it.items(db), 58 Container::ImplBlock(it) => it.id.child_from_source(db, src),
56 Container::Module(m) => { 59 Container::Module(it) => it.id.child_from_source(db, src),
57 return m 60 }
58 .declarations(db) 61 .map(Function::from)
59 .into_iter()
60 .filter_map(|it| match it {
61 ModuleDef::Function(it) => Some(it),
62 _ => None,
63 })
64 .find(|it| same_source(&it.source(db), &src))
65 }
66 };
67 items
68 .into_iter()
69 .filter_map(|it| match it {
70 AssocItem::Function(it) => Some(it),
71 _ => None,
72 })
73 .find(|it| same_source(&it.source(db), &src))
74 } 62 }
75} 63}
76 64
77impl FromSource for Const { 65impl FromSource for Const {
78 type Ast = ast::ConstDef; 66 type Ast = ast::ConstDef;
79 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 67 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
80 let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { 68 match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
81 Container::Trait(it) => it.items(db), 69 Container::Trait(it) => it.id.child_from_source(db, src),
82 Container::ImplBlock(it) => it.items(db), 70 Container::ImplBlock(it) => it.id.child_from_source(db, src),
83 Container::Module(m) => { 71 Container::Module(it) => it.id.child_from_source(db, src),
84 return m 72 }
85 .declarations(db) 73 .map(Const::from)
86 .into_iter()
87 .filter_map(|it| match it {
88 ModuleDef::Const(it) => Some(it),
89 _ => None,
90 })
91 .find(|it| same_source(&it.source(db), &src))
92 }
93 };
94 items
95 .into_iter()
96 .filter_map(|it| match it {
97 AssocItem::Const(it) => Some(it),
98 _ => None,
99 })
100 .find(|it| same_source(&it.source(db), &src))
101 } 74 }
102} 75}
103impl FromSource for Static { 76impl FromSource for Static {
104 type Ast = ast::StaticDef; 77 type Ast = ast::StaticDef;
105 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 78 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
106 let module = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { 79 match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
107 Container::Module(it) => it, 80 Container::Module(it) => it.id.child_from_source(db, src).map(Static::from),
108 Container::Trait(_) | Container::ImplBlock(_) => return None, 81 Container::Trait(_) | Container::ImplBlock(_) => None,
109 }; 82 }
110 module
111 .declarations(db)
112 .into_iter()
113 .filter_map(|it| match it {
114 ModuleDef::Static(it) => Some(it),
115 _ => None,
116 })
117 .find(|it| same_source(&it.source(db), &src))
118 } 83 }
119} 84}
120 85
121impl FromSource for TypeAlias { 86impl FromSource for TypeAlias {
122 type Ast = ast::TypeAliasDef; 87 type Ast = ast::TypeAliasDef;
123 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 88 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
124 let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { 89 match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
125 Container::Trait(it) => it.items(db), 90 Container::Trait(it) => it.id.child_from_source(db, src),
126 Container::ImplBlock(it) => it.items(db), 91 Container::ImplBlock(it) => it.id.child_from_source(db, src),
127 Container::Module(m) => { 92 Container::Module(it) => it.id.child_from_source(db, src),
128 return m 93 }
129 .declarations(db) 94 .map(TypeAlias::from)
130 .into_iter()
131 .filter_map(|it| match it {
132 ModuleDef::TypeAlias(it) => Some(it),
133 _ => None,
134 })
135 .find(|it| same_source(&it.source(db), &src))
136 }
137 };
138 items
139 .into_iter()
140 .filter_map(|it| match it {
141 AssocItem::TypeAlias(it) => Some(it),
142 _ => None,
143 })
144 .find(|it| same_source(&it.source(db), &src))
145 } 95 }
146} 96}
147 97
@@ -174,34 +124,33 @@ impl FromSource for EnumVariant {
174 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 124 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
175 let parent_enum = src.value.parent_enum(); 125 let parent_enum = src.value.parent_enum();
176 let src_enum = InFile { file_id: src.file_id, value: parent_enum }; 126 let src_enum = InFile { file_id: src.file_id, value: parent_enum };
177 let variants = Enum::from_source(db, src_enum)?.variants(db); 127 let parent_enum = Enum::from_source(db, src_enum)?;
178 variants.into_iter().find(|v| same_source(&v.source(db), &src)) 128 parent_enum.id.child_from_source(db, src).map(EnumVariant::from)
179 } 129 }
180} 130}
181 131
182impl FromSource for StructField { 132impl FromSource for StructField {
183 type Ast = FieldSource; 133 type Ast = FieldSource;
184 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> { 134 fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
185 let variant_def: VariantDef = match src.value { 135 let variant_id: VariantId = match src.value {
186 FieldSource::Named(ref field) => { 136 FieldSource::Named(ref field) => {
187 let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; 137 let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
188 let src = InFile { file_id: src.file_id, value }; 138 let src = InFile { file_id: src.file_id, value };
189 let def = Struct::from_source(db, src)?; 139 let def = Struct::from_source(db, src)?;
190 VariantDef::from(def) 140 def.id.into()
191 } 141 }
192 FieldSource::Pos(ref field) => { 142 FieldSource::Pos(ref field) => {
193 let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; 143 let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
194 let src = InFile { file_id: src.file_id, value }; 144 let src = InFile { file_id: src.file_id, value };
195 let def = EnumVariant::from_source(db, src)?; 145 let def = EnumVariant::from_source(db, src)?;
196 VariantDef::from(def) 146 EnumVariantId::from(def).into()
197 } 147 }
198 }; 148 };
199 variant_def 149 let src = src.map(|field_source| match field_source {
200 .variant_data(db) 150 FieldSource::Pos(it) => Either::Left(it),
201 .fields() 151 FieldSource::Named(it) => Either::Right(it),
202 .iter() 152 });
203 .map(|(id, _)| StructField { parent: variant_def, id }) 153 variant_id.child_from_source(db, src).map(StructField::from)
204 .find(|f| f.source(db) == src)
205 } 154 }
206} 155}
207 156
@@ -314,13 +263,3 @@ impl Container {
314 Some(Container::Module(c)) 263 Some(Container::Module(c))
315 } 264 }
316} 265}
317
318/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
319/// equal if they point to exactly the same object.
320///
321/// In general, we do not guarantee that we have exactly one instance of a
322/// syntax tree for each file. We probably should add such guarantee, but, for
323/// the time being, we will use identity-less AstPtr comparison.
324fn same_source<N: AstNode>(s1: &InFile<N>, s2: &InFile<N>) -> bool {
325 s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new)
326}