|
1 | 1 | //! FIXME: write short doc here
|
| 2 | +use either::Either; |
2 | 3 |
|
3 |
| -use hir_def::{AstItemDef, LocationCtx, ModuleId}; |
| 4 | +use hir_def::{ |
| 5 | + child_from_source::ChildFromSource, AstItemDef, EnumVariantId, LocationCtx, ModuleId, VariantId, |
| 6 | +}; |
4 | 7 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
|
5 | 8 | use ra_syntax::{
|
6 | 9 | ast::{self, AstNode, NameOwner},
|
7 |
| - match_ast, AstPtr, SyntaxNode, |
| 10 | + match_ast, SyntaxNode, |
8 | 11 | };
|
9 | 12 |
|
10 | 13 | use crate::{
|
11 | 14 | db::{AstDatabase, DefDatabase, HirDatabase},
|
12 |
| - AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, |
13 |
| - InFile, Local, MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, |
14 |
| - TypeAlias, Union, VariantDef, |
| 15 | + Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, |
| 16 | + MacroDef, Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, |
15 | 17 | };
|
16 | 18 |
|
17 | 19 | pub trait FromSource: Sized {
|
@@ -50,98 +52,45 @@ impl FromSource for Trait {
|
50 | 52 | impl FromSource for Function {
|
51 | 53 | type Ast = ast::FnDef;
|
52 | 54 | 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)) |
| 55 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 56 | + Container::Trait(it) => it.id.child_from_source(db, src), |
| 57 | + Container::ImplBlock(it) => it.id.child_from_source(db, src), |
| 58 | + Container::Module(it) => it.id.child_from_source(db, src), |
| 59 | + } |
| 60 | + .map(Function::from) |
74 | 61 | }
|
75 | 62 | }
|
76 | 63 |
|
77 | 64 | impl FromSource for Const {
|
78 | 65 | type Ast = ast::ConstDef;
|
79 | 66 | 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)) |
| 67 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 68 | + Container::Trait(it) => it.id.child_from_source(db, src), |
| 69 | + Container::ImplBlock(it) => it.id.child_from_source(db, src), |
| 70 | + Container::Module(it) => it.id.child_from_source(db, src), |
| 71 | + } |
| 72 | + .map(Const::from) |
101 | 73 | }
|
102 | 74 | }
|
103 | 75 | impl FromSource for Static {
|
104 | 76 | type Ast = ast::StaticDef;
|
105 | 77 | 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)) |
| 78 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 79 | + Container::Module(it) => it.id.child_from_source(db, src).map(Static::from), |
| 80 | + Container::Trait(_) | Container::ImplBlock(_) => None, |
| 81 | + } |
118 | 82 | }
|
119 | 83 | }
|
120 | 84 |
|
121 | 85 | impl FromSource for TypeAlias {
|
122 | 86 | type Ast = ast::TypeAliasDef;
|
123 | 87 | 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)) |
| 88 | + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { |
| 89 | + Container::Trait(it) => it.id.child_from_source(db, src), |
| 90 | + Container::ImplBlock(it) => it.id.child_from_source(db, src), |
| 91 | + Container::Module(it) => it.id.child_from_source(db, src), |
| 92 | + } |
| 93 | + .map(TypeAlias::from) |
145 | 94 | }
|
146 | 95 | }
|
147 | 96 |
|
@@ -174,34 +123,33 @@ impl FromSource for EnumVariant {
|
174 | 123 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
|
175 | 124 | let parent_enum = src.value.parent_enum();
|
176 | 125 | 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)) |
| 126 | + let parent_enum = Enum::from_source(db, src_enum)?; |
| 127 | + parent_enum.id.child_from_source(db, src).map(EnumVariant::from) |
179 | 128 | }
|
180 | 129 | }
|
181 | 130 |
|
182 | 131 | impl FromSource for StructField {
|
183 | 132 | type Ast = FieldSource;
|
184 | 133 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
|
185 |
| - let variant_def: VariantDef = match src.value { |
| 134 | + let variant_id: VariantId = match src.value { |
186 | 135 | FieldSource::Named(ref field) => {
|
187 | 136 | let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
|
188 | 137 | let src = InFile { file_id: src.file_id, value };
|
189 | 138 | let def = Struct::from_source(db, src)?;
|
190 |
| - VariantDef::from(def) |
| 139 | + def.id.into() |
191 | 140 | }
|
192 | 141 | FieldSource::Pos(ref field) => {
|
193 | 142 | let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
|
194 | 143 | let src = InFile { file_id: src.file_id, value };
|
195 | 144 | let def = EnumVariant::from_source(db, src)?;
|
196 |
| - VariantDef::from(def) |
| 145 | + EnumVariantId::from(def).into() |
197 | 146 | }
|
198 | 147 | };
|
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) |
| 148 | + let src = src.map(|field_source| match field_source { |
| 149 | + FieldSource::Pos(it) => Either::Left(it), |
| 150 | + FieldSource::Named(it) => Either::Right(it), |
| 151 | + }); |
| 152 | + variant_id.child_from_source(db, src).map(StructField::from) |
205 | 153 | }
|
206 | 154 | }
|
207 | 155 |
|
@@ -315,13 +263,3 @@ impl Container {
|
315 | 263 | Some(Container::Module(c))
|
316 | 264 | }
|
317 | 265 | }
|
318 |
| - |
319 |
| -/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are |
320 |
| -/// equal if they point to exactly the same object. |
321 |
| -/// |
322 |
| -/// In general, we do not guarantee that we have exactly one instance of a |
323 |
| -/// syntax tree for each file. We probably should add such guarantee, but, for |
324 |
| -/// the time being, we will use identity-less AstPtr comparison. |
325 |
| -fn same_source<N: AstNode>(s1: &InFile<N>, s2: &InFile<N>) -> bool { |
326 |
| - s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) |
327 |
| -} |
0 commit comments