Skip to content

Commit 217a6fa

Browse files
bors[bot]matklad
andauthored
Merge #2480
2480: New from sorce infra r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 4c0bd06 + 1a567f5 commit 217a6fa

File tree

3 files changed

+325
-99
lines changed

3 files changed

+325
-99
lines changed

crates/ra_hir/src/from_source.rs

+48-99
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
//! FIXME: write short doc here
2+
use either::Either;
23

3-
use hir_def::{nameres::ModuleSource, AstItemDef, LocationCtx, ModuleId};
4+
use hir_def::{
5+
child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, ImplId,
6+
LocationCtx, ModuleId, TraitId, VariantId,
7+
};
48
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
59
use ra_syntax::{
610
ast::{self, AstNode, NameOwner},
7-
match_ast, AstPtr, SyntaxNode,
11+
match_ast, SyntaxNode,
812
};
913

1014
use crate::{
1115
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,
1518
};
1619

1720
pub trait FromSource: Sized {
@@ -50,98 +53,36 @@ impl FromSource for Trait {
5053
impl FromSource for Function {
5154
type Ast = ast::FnDef;
5255
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+
Container::find(db, src.as_ref().map(|it| it.syntax()))?
57+
.child_from_source(db, src)
58+
.map(Function::from)
7459
}
7560
}
7661

7762
impl FromSource for Const {
7863
type Ast = ast::ConstDef;
7964
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))
65+
Container::find(db, src.as_ref().map(|it| it.syntax()))?
66+
.child_from_source(db, src)
67+
.map(Const::from)
10168
}
10269
}
10370
impl FromSource for Static {
10471
type Ast = ast::StaticDef;
10572
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))
73+
match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
74+
Container::Module(it) => it.id.child_from_source(db, src).map(Static::from),
75+
Container::Trait(_) | Container::ImplBlock(_) => None,
76+
}
11877
}
11978
}
12079

12180
impl FromSource for TypeAlias {
12281
type Ast = ast::TypeAliasDef;
12382
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))
83+
Container::find(db, src.as_ref().map(|it| it.syntax()))?
84+
.child_from_source(db, src)
85+
.map(TypeAlias::from)
14586
}
14687
}
14788

@@ -174,34 +115,33 @@ impl FromSource for EnumVariant {
174115
fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
175116
let parent_enum = src.value.parent_enum();
176117
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))
118+
let parent_enum = Enum::from_source(db, src_enum)?;
119+
parent_enum.id.child_from_source(db, src).map(EnumVariant::from)
179120
}
180121
}
181122

182123
impl FromSource for StructField {
183124
type Ast = FieldSource;
184125
fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
185-
let variant_def: VariantDef = match src.value {
126+
let variant_id: VariantId = match src.value {
186127
FieldSource::Named(ref field) => {
187128
let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
188129
let src = InFile { file_id: src.file_id, value };
189130
let def = Struct::from_source(db, src)?;
190-
VariantDef::from(def)
131+
def.id.into()
191132
}
192133
FieldSource::Pos(ref field) => {
193134
let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
194135
let src = InFile { file_id: src.file_id, value };
195136
let def = EnumVariant::from_source(db, src)?;
196-
VariantDef::from(def)
137+
EnumVariantId::from(def).into()
197138
}
198139
};
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)
140+
let src = src.map(|field_source| match field_source {
141+
FieldSource::Pos(it) => Either::Left(it),
142+
FieldSource::Named(it) => Either::Right(it),
143+
});
144+
variant_id.child_from_source(db, src).map(StructField::from)
205145
}
206146
}
207147

@@ -315,12 +255,21 @@ impl Container {
315255
}
316256
}
317257

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)
258+
impl<CHILD, SOURCE> ChildFromSource<CHILD, SOURCE> for Container
259+
where
260+
TraitId: ChildFromSource<CHILD, SOURCE>,
261+
ImplId: ChildFromSource<CHILD, SOURCE>,
262+
ModuleId: ChildFromSource<CHILD, SOURCE>,
263+
{
264+
fn child_from_source(
265+
&self,
266+
db: &impl DefDatabase,
267+
child_source: InFile<SOURCE>,
268+
) -> Option<CHILD> {
269+
match self {
270+
Container::Trait(it) => it.id.child_from_source(db, child_source),
271+
Container::ImplBlock(it) => it.id.child_from_source(db, child_source),
272+
Container::Module(it) => it.id.child_from_source(db, child_source),
273+
}
274+
}
326275
}

0 commit comments

Comments
 (0)