|
1 | 1 | //! FIXME: write short doc here
|
| 2 | +use either::Either; |
2 | 3 |
|
3 |
| -use hir_def::{nameres::ModuleSource, AstItemDef, LocationCtx, ModuleId}; |
| 4 | +use hir_def::{ |
| 5 | + child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, |
| 6 | + LocationCtx, ModuleId, VariantId, |
| 7 | +}; |
4 | 8 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
|
5 | 9 | use ra_syntax::{
|
6 | 10 | ast::{self, AstNode, NameOwner},
|
7 |
| - match_ast, AstPtr, SyntaxNode, |
| 11 | + match_ast, SyntaxNode, |
8 | 12 | };
|
9 | 13 |
|
10 | 14 | use crate::{
|
11 | 15 | db::{AstDatabase, DefDatabase, HirDatabase},
|
12 |
| - AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, |
13 |
| - InFile, Local, MacroDef, Module, ModuleDef, Static, Struct, StructField, Trait, TypeAlias, |
14 |
| - Union, VariantDef, |
| 16 | + Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, |
| 17 | + MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, |
15 | 18 | };
|
16 | 19 |
|
17 | 20 | pub trait FromSource: Sized {
|
@@ -50,98 +53,45 @@ impl FromSource for Trait {
|
50 | 53 | impl FromSource for Function {
|
51 | 54 | type Ast = ast::FnDef;
|
52 | 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()))? { |
54 |
| - Container::Trait(it) => it.items(db), |
55 |
| - Container::ImplBlock(it) => it.items(db), |
56 |
| - Container::Module(m) => { |
57 |
| - return m |
58 |
| - .declarations(db) |
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)) |
| 56 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 57 | + Container::Trait(it) => it.id.child_from_source(db, src), |
| 58 | + Container::ImplBlock(it) => it.id.child_from_source(db, src), |
| 59 | + Container::Module(it) => it.id.child_from_source(db, src), |
| 60 | + } |
| 61 | + .map(Function::from) |
74 | 62 | }
|
75 | 63 | }
|
76 | 64 |
|
77 | 65 | impl FromSource for Const {
|
78 | 66 | type Ast = ast::ConstDef;
|
79 | 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()))? { |
81 |
| - Container::Trait(it) => it.items(db), |
82 |
| - Container::ImplBlock(it) => it.items(db), |
83 |
| - Container::Module(m) => { |
84 |
| - return m |
85 |
| - .declarations(db) |
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)) |
| 68 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 69 | + Container::Trait(it) => it.id.child_from_source(db, src), |
| 70 | + Container::ImplBlock(it) => it.id.child_from_source(db, src), |
| 71 | + Container::Module(it) => it.id.child_from_source(db, src), |
| 72 | + } |
| 73 | + .map(Const::from) |
101 | 74 | }
|
102 | 75 | }
|
103 | 76 | impl FromSource for Static {
|
104 | 77 | type Ast = ast::StaticDef;
|
105 | 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()))? { |
107 |
| - Container::Module(it) => it, |
108 |
| - Container::Trait(_) | Container::ImplBlock(_) => return None, |
109 |
| - }; |
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)) |
| 79 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 80 | + Container::Module(it) => it.id.child_from_source(db, src).map(Static::from), |
| 81 | + Container::Trait(_) | Container::ImplBlock(_) => None, |
| 82 | + } |
118 | 83 | }
|
119 | 84 | }
|
120 | 85 |
|
121 | 86 | impl FromSource for TypeAlias {
|
122 | 87 | type Ast = ast::TypeAliasDef;
|
123 | 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()))? { |
125 |
| - Container::Trait(it) => it.items(db), |
126 |
| - Container::ImplBlock(it) => it.items(db), |
127 |
| - Container::Module(m) => { |
128 |
| - return m |
129 |
| - .declarations(db) |
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)) |
| 89 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 90 | + Container::Trait(it) => it.id.child_from_source(db, src), |
| 91 | + Container::ImplBlock(it) => it.id.child_from_source(db, src), |
| 92 | + Container::Module(it) => it.id.child_from_source(db, src), |
| 93 | + } |
| 94 | + .map(TypeAlias::from) |
145 | 95 | }
|
146 | 96 | }
|
147 | 97 |
|
@@ -174,34 +124,33 @@ impl FromSource for EnumVariant {
|
174 | 124 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
|
175 | 125 | let parent_enum = src.value.parent_enum();
|
176 | 126 | let src_enum = InFile { file_id: src.file_id, value: parent_enum };
|
177 |
| - let variants = Enum::from_source(db, src_enum)?.variants(db); |
178 |
| - variants.into_iter().find(|v| same_source(&v.source(db), &src)) |
| 127 | + let parent_enum = Enum::from_source(db, src_enum)?; |
| 128 | + parent_enum.id.child_from_source(db, src).map(EnumVariant::from) |
179 | 129 | }
|
180 | 130 | }
|
181 | 131 |
|
182 | 132 | impl FromSource for StructField {
|
183 | 133 | type Ast = FieldSource;
|
184 | 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 | 136 | FieldSource::Named(ref field) => {
|
187 | 137 | let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
|
188 | 138 | let src = InFile { file_id: src.file_id, value };
|
189 | 139 | let def = Struct::from_source(db, src)?;
|
190 |
| - VariantDef::from(def) |
| 140 | + def.id.into() |
191 | 141 | }
|
192 | 142 | FieldSource::Pos(ref field) => {
|
193 | 143 | let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
|
194 | 144 | let src = InFile { file_id: src.file_id, value };
|
195 | 145 | let def = EnumVariant::from_source(db, src)?;
|
196 |
| - VariantDef::from(def) |
| 146 | + EnumVariantId::from(def).into() |
197 | 147 | }
|
198 | 148 | };
|
199 |
| - variant_def |
200 |
| - .variant_data(db) |
201 |
| - .fields() |
202 |
| - .iter() |
203 |
| - .map(|(id, _)| StructField { parent: variant_def, id }) |
204 |
| - .find(|f| f.source(db) == src) |
| 149 | + let src = src.map(|field_source| match field_source { |
| 150 | + FieldSource::Pos(it) => Either::Left(it), |
| 151 | + FieldSource::Named(it) => Either::Right(it), |
| 152 | + }); |
| 153 | + variant_id.child_from_source(db, src).map(StructField::from) |
205 | 154 | }
|
206 | 155 | }
|
207 | 156 |
|
@@ -314,13 +263,3 @@ impl Container {
|
314 | 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. |
324 |
| -fn 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 |
| -} |
0 commit comments