aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs7
-rw-r--r--crates/ra_hir_def/src/item_tree.rs511
-rw-r--r--crates/ra_hir_def/src/lib.rs2
3 files changed, 517 insertions, 3 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f159f80af..113ec2b78 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -3,6 +3,7 @@
3 3
4use either::Either; 4use either::Either;
5use hir_expand::{ 5use hir_expand::{
6 db::AstDatabase,
6 hygiene::Hygiene, 7 hygiene::Hygiene,
7 name::{name, AsName, Name}, 8 name::{name, AsName, Name},
8 HirFileId, MacroDefId, MacroDefKind, 9 HirFileId, MacroDefId, MacroDefKind,
@@ -41,8 +42,8 @@ pub(crate) struct LowerCtx {
41} 42}
42 43
43impl LowerCtx { 44impl LowerCtx {
44 pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self { 45 pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Self {
45 LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) } 46 LowerCtx { hygiene: Hygiene::new(db, file_id) }
46 } 47 }
47 pub fn with_hygiene(hygiene: &Hygiene) -> Self { 48 pub fn with_hygiene(hygiene: &Hygiene) -> Self {
48 LowerCtx { hygiene: hygiene.clone() } 49 LowerCtx { hygiene: hygiene.clone() }
@@ -119,7 +120,7 @@ impl ExprCollector<'_> {
119 } 120 }
120 121
121 fn ctx(&self) -> LowerCtx { 122 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id) 123 LowerCtx::new(self.db.upcast(), self.expander.current_file_id)
123 } 124 }
124 125
125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 126 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs
new file mode 100644
index 000000000..f4743f0f6
--- /dev/null
+++ b/crates/ra_hir_def/src/item_tree.rs
@@ -0,0 +1,511 @@
1//! A simplified AST that only contains items.
2
3use hir_expand::{
4 ast_id_map::{AstIdMap, FileAstId},
5 hygiene::Hygiene,
6 name::{name, AsName, Name},
7};
8use ra_arena::{Arena, Idx, RawId};
9use ra_syntax::ast;
10
11use crate::{
12 attr::Attrs,
13 generics::GenericParams,
14 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path},
15 type_ref::{Mutability, TypeBound, TypeRef},
16 visibility::RawVisibility,
17};
18use ast::{NameOwner, StructKind, TypeAscriptionOwner};
19use std::{
20 ops::{Index, Range},
21 sync::Arc,
22};
23
24#[derive(Default)]
25pub struct ItemTree {
26 imports: Arena<Import>,
27 functions: Arena<Function>,
28 structs: Arena<Struct>,
29 fields: Arena<Field>,
30 unions: Arena<Union>,
31 enums: Arena<Enum>,
32 variants: Arena<Variant>,
33 consts: Arena<Const>,
34 statics: Arena<Static>,
35 traits: Arena<Trait>,
36 impls: Arena<Impl>,
37 type_aliases: Arena<TypeAlias>,
38 mods: Arena<Mod>,
39 macro_calls: Arena<MacroCall>,
40 exprs: Arena<Expr>,
41}
42
43impl ItemTree {
44 pub fn query(syntax: &ast::SourceFile) -> ItemTree {
45 todo!()
46 }
47}
48
49macro_rules! impl_index {
50 ( $($fld:ident: $t:ty),+ $(,)? ) => {
51 $(
52 impl Index<Idx<$t>> for ItemTree {
53 type Output = $t;
54
55 fn index(&self, index: Idx<$t>) -> &Self::Output {
56 &self.$fld[index]
57 }
58 }
59 )+
60 };
61}
62
63impl_index!(
64 imports: Import,
65 functions: Function,
66 structs: Struct,
67 fields: Field,
68 unions: Union,
69 enums: Enum,
70 variants: Variant,
71 consts: Const,
72 statics: Static,
73 traits: Trait,
74 impls: Impl,
75 type_aliases: TypeAlias,
76 mods: Mod,
77 macro_calls: MacroCall,
78 exprs: Expr,
79);
80
81pub struct Import {
82 pub path: ModPath,
83 pub alias: Option<ImportAlias>,
84 pub visibility: RawVisibility,
85 pub is_glob: bool,
86 pub is_prelude: bool,
87 pub is_extern_crate: bool,
88 pub is_macro_use: bool,
89}
90
91pub struct Function {
92 pub name: Name,
93 pub attrs: Attrs,
94 pub visibility: RawVisibility,
95 pub generic_params: GenericParams,
96 pub has_self_param: bool,
97 pub params: Vec<TypeRef>,
98 pub ret_type: TypeRef,
99 pub ast: FileAstId<ast::FnDef>,
100}
101
102pub struct Struct {
103 pub name: Name,
104 pub attrs: Attrs,
105 pub visibility: RawVisibility,
106 pub generic_params: GenericParams,
107 pub fields: Fields,
108 pub ast: FileAstId<ast::StructDef>,
109}
110
111pub struct Union {
112 pub name: Name,
113 pub attrs: Attrs,
114 pub visibility: RawVisibility,
115 pub generic_params: GenericParams,
116 pub fields: Fields,
117}
118
119pub struct Enum {
120 pub name: Name,
121 pub attrs: Attrs,
122 pub visibility: RawVisibility,
123 pub generic_params: GenericParams,
124 pub variants: Range<Idx<Variant>>,
125}
126
127pub struct Const {
128 /// const _: () = ();
129 pub name: Option<Name>,
130 pub visibility: RawVisibility,
131 pub type_ref: TypeRef,
132}
133
134pub struct Static {
135 pub name: Name,
136 pub visibility: RawVisibility,
137 pub type_ref: TypeRef,
138}
139
140pub struct Trait {
141 pub name: Name,
142 pub visibility: RawVisibility,
143 pub generic_params: GenericParams,
144 pub auto: bool,
145 pub items: Vec<AssocItem>,
146}
147
148pub struct Impl {
149 pub generic_params: GenericParams,
150 pub target_trait: Option<TypeRef>,
151 pub target_type: TypeRef,
152 pub is_negative: bool,
153 pub items: Vec<AssocItem>,
154}
155
156#[derive(Debug, Clone, PartialEq, Eq)]
157pub struct TypeAlias {
158 pub name: Name,
159 pub visibility: RawVisibility,
160 pub generic_params: GenericParams,
161 pub type_ref: Option<TypeRef>,
162}
163
164pub struct Mod {
165 pub name: Name,
166 pub visibility: RawVisibility,
167 pub items: Vec<ModItem>,
168}
169
170pub struct MacroCall {
171 pub name: Option<Name>,
172 pub path: ModPath,
173 pub export: bool,
174 pub builtin: bool,
175 pub ast_id: FileAstId<ast::MacroCall>,
176}
177
178// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
179// lengths, but we don't do much with them yet.
180pub struct Expr;
181
182pub enum ModItem {
183 Import(Idx<Import>),
184 Function(Idx<Function>),
185 Struct(Idx<Struct>),
186 Union(Idx<Union>),
187 Enum(Idx<Enum>),
188 Const(Idx<Const>),
189 Static(Idx<Static>),
190 Trait(Idx<Trait>),
191 Impl(Idx<Impl>),
192 TypeAlias(Idx<TypeAlias>),
193 Mod(Idx<Mod>),
194 MacroCall(Idx<MacroCall>),
195}
196
197pub enum AssocItem {
198 Function(Idx<Function>),
199 TypeAlias(Idx<TypeAlias>),
200 Const(Idx<Const>),
201 MacroCall(Idx<MacroCall>),
202}
203
204pub struct Variant {
205 pub name: Name,
206 pub fields: Fields,
207}
208
209#[derive(Debug, Clone, PartialEq, Eq)]
210pub enum Fields {
211 Record(Range<Idx<Field>>),
212 Tuple(Range<Idx<Field>>),
213 Unit,
214}
215
216/// A single field of an enum variant or struct
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct Field {
219 pub name: Name,
220 pub type_ref: TypeRef,
221 pub visibility: RawVisibility,
222}
223
224struct Ctx {
225 tree: ItemTree,
226 hygiene: Hygiene,
227 source_ast_id_map: Arc<AstIdMap>,
228 body_ctx: crate::body::LowerCtx,
229}
230
231impl Ctx {
232 fn lower(&mut self, item_owner: &dyn ast::ModuleItemOwner) {
233 for item in item_owner.items() {
234 self.lower_item(&item)
235 }
236 }
237
238 fn lower_item(&mut self, item: &ast::ModuleItem) {
239 match item {
240 ast::ModuleItem::StructDef(ast) => {
241 if let Some(data) = self.lower_struct(ast) {
242 let idx = self.tree.structs.alloc(data);
243 }
244 }
245 ast::ModuleItem::UnionDef(ast) => {
246 if let Some(data) = self.lower_union(ast) {
247 let idx = self.tree.unions.alloc(data);
248 }
249 }
250 ast::ModuleItem::EnumDef(ast) => {
251 if let Some(data) = self.lower_enum(ast) {
252 let idx = self.tree.enums.alloc(data);
253 }
254 }
255 ast::ModuleItem::FnDef(ast) => {
256 if let Some(data) = self.lower_function(ast) {
257 let idx = self.tree.functions.alloc(data);
258 }
259 }
260 ast::ModuleItem::TypeAliasDef(ast) => {
261 if let Some(data) = self.lower_type_alias(ast) {
262 let idx = self.tree.type_aliases.alloc(data);
263 }
264 }
265 ast::ModuleItem::StaticDef(ast) => {
266 if let Some(data) = self.lower_static(ast) {
267 let idx = self.tree.statics.alloc(data);
268 }
269 }
270 ast::ModuleItem::ConstDef(ast) => {
271 let data = self.lower_const(ast);
272 let idx = self.tree.consts.alloc(data);
273 }
274 ast::ModuleItem::Module(_) => {}
275 ast::ModuleItem::TraitDef(_) => {}
276 ast::ModuleItem::ImplDef(_) => {}
277 ast::ModuleItem::UseItem(_) => {}
278 ast::ModuleItem::ExternCrateItem(_) => {}
279 ast::ModuleItem::MacroCall(_) => {}
280 ast::ModuleItem::ExternBlock(_) => {}
281 }
282 }
283
284 fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<Struct> {
285 let attrs = self.lower_attrs(strukt);
286 let visibility = self.lower_visibility(strukt);
287 let name = strukt.name()?.as_name();
288 let generic_params = self.lower_generic_params(strukt);
289 let fields = self.lower_fields(&strukt.kind());
290 let ast = self.source_ast_id_map.ast_id(strukt);
291 let res = Struct { name, attrs, visibility, generic_params, fields, ast };
292 Some(res)
293 }
294
295 fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields {
296 match strukt_kind {
297 ast::StructKind::Record(it) => {
298 let range = self.lower_record_fields(it);
299 Fields::Record(range)
300 }
301 ast::StructKind::Tuple(it) => {
302 let range = self.lower_tuple_fields(it);
303 Fields::Tuple(range)
304 }
305 ast::StructKind::Unit => Fields::Unit,
306 }
307 }
308
309 fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> Range<Idx<Field>> {
310 let start = self.next_field_idx();
311 for field in fields.fields() {
312 if let Some(data) = self.lower_record_field(&field) {
313 let idx = self.tree.fields.alloc(data);
314 }
315 }
316 let end = self.next_field_idx();
317 start..end
318 }
319
320 fn lower_record_field(&self, field: &ast::RecordFieldDef) -> Option<Field> {
321 let name = field.name()?.as_name();
322 let visibility = self.lower_visibility(field);
323 let type_ref = self.lower_type_ref(&field.ascribed_type()?);
324 let res = Field { name, type_ref, visibility };
325 Some(res)
326 }
327
328 fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> Range<Idx<Field>> {
329 let start = self.next_field_idx();
330 for (i, field) in fields.fields().enumerate() {
331 if let Some(data) = self.lower_tuple_field(i, &field) {
332 let idx = self.tree.fields.alloc(data);
333 }
334 }
335 let end = self.next_field_idx();
336 start..end
337 }
338
339 fn lower_tuple_field(&self, idx: usize, field: &ast::TupleFieldDef) -> Option<Field> {
340 let name = Name::new_tuple_field(idx);
341 let visibility = self.lower_visibility(field);
342 let type_ref = self.lower_type_ref(&field.type_ref()?);
343 let res = Field { name, type_ref, visibility };
344 Some(res)
345 }
346
347 fn lower_union(&mut self, union: &ast::UnionDef) -> Option<Union> {
348 let attrs = self.lower_attrs(union);
349 let visibility = self.lower_visibility(union);
350 let name = union.name()?.as_name();
351 let generic_params = self.lower_generic_params(union);
352 let fields = match union.record_field_def_list() {
353 Some(record_field_def_list) => {
354 self.lower_fields(&StructKind::Record(record_field_def_list))
355 }
356 None => Fields::Record(self.next_field_idx()..self.next_field_idx()),
357 };
358 let res = Union { name, attrs, visibility, generic_params, fields };
359 Some(res)
360 }
361
362 fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<Enum> {
363 let attrs = self.lower_attrs(enum_);
364 let visibility = self.lower_visibility(enum_);
365 let name = enum_.name()?.as_name();
366 let generic_params = self.lower_generic_params(enum_);
367 let variants = match &enum_.variant_list() {
368 Some(variant_list) => self.lower_variants(variant_list),
369 None => self.next_variant_idx()..self.next_variant_idx(),
370 };
371 let res = Enum { name, attrs, visibility, generic_params, variants };
372 Some(res)
373 }
374
375 fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> Range<Idx<Variant>> {
376 let start = self.next_variant_idx();
377 for variant in variants.variants() {
378 if let Some(data) = self.lower_variant(&variant) {
379 let idx = self.tree.variants.alloc(data);
380 }
381 }
382 let end = self.next_variant_idx();
383 start..end
384 }
385
386 fn lower_variant(&mut self, variant: &ast::EnumVariant) -> Option<Variant> {
387 let name = variant.name()?.as_name();
388 let fields = self.lower_fields(&variant.kind());
389 let res = Variant { name, fields };
390 Some(res)
391 }
392
393 fn lower_function(&mut self, func: &ast::FnDef) -> Option<Function> {
394 let attrs = self.lower_attrs(func);
395 let visibility = self.lower_visibility(func);
396 let name = func.name()?.as_name();
397 let generic_params = self.lower_generic_params(func);
398
399 let mut params = Vec::new();
400 let mut has_self_param = false;
401 if let Some(param_list) = func.param_list() {
402 if let Some(self_param) = param_list.self_param() {
403 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
404 TypeRef::from_ast(&self.body_ctx, type_ref)
405 } else {
406 let self_type = TypeRef::Path(name![Self].into());
407 match self_param.kind() {
408 ast::SelfParamKind::Owned => self_type,
409 ast::SelfParamKind::Ref => {
410 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
411 }
412 ast::SelfParamKind::MutRef => {
413 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
414 }
415 }
416 };
417 params.push(self_type);
418 has_self_param = true;
419 }
420 for param in param_list.params() {
421 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ascribed_type());
422 params.push(type_ref);
423 }
424 }
425 let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) {
426 Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
427 _ => TypeRef::unit(),
428 };
429
430 let ret_type = if func.async_token().is_some() {
431 let future_impl = desugar_future_path(ret_type);
432 let ty_bound = TypeBound::Path(future_impl);
433 TypeRef::ImplTrait(vec![ty_bound])
434 } else {
435 ret_type
436 };
437
438 let ast = self.source_ast_id_map.ast_id(func);
439 let res = Function {
440 name,
441 attrs,
442 visibility,
443 generic_params,
444 has_self_param,
445 params,
446 ret_type,
447 ast,
448 };
449 Some(res)
450 }
451
452 fn lower_type_alias(&mut self, type_alias: &ast::TypeAliasDef) -> Option<TypeAlias> {
453 let name = type_alias.name()?.as_name();
454 let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it));
455 let visibility = self.lower_visibility(type_alias);
456 let generic_params = self.lower_generic_params(type_alias);
457 let res = TypeAlias { name, visibility, generic_params, type_ref };
458 Some(res)
459 }
460
461 fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<Static> {
462 let name = static_.name()?.as_name();
463 let type_ref = self.lower_type_ref_opt(static_.ascribed_type());
464 let visibility = self.lower_visibility(static_);
465 let res = Static { name, visibility, type_ref };
466 Some(res)
467 }
468
469 fn lower_const(&mut self, konst: &ast::ConstDef) -> Const {
470 let name = konst.name().map(|it| it.as_name());
471 let type_ref = self.lower_type_ref_opt(konst.ascribed_type());
472 let visibility = self.lower_visibility(konst);
473 Const { name, visibility, type_ref }
474 }
475
476 fn lower_generic_params(&mut self, item: &impl ast::TypeParamsOwner) -> GenericParams {
477 None.unwrap()
478 }
479
480 fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
481 Attrs::new(item, &self.hygiene)
482 }
483 fn lower_visibility(&self, item: &impl ast::VisibilityOwner) -> RawVisibility {
484 RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene)
485 }
486 fn lower_type_ref(&self, type_ref: &ast::TypeRef) -> TypeRef {
487 TypeRef::from_ast(&self.body_ctx, type_ref.clone())
488 }
489 fn lower_type_ref_opt(&self, type_ref: Option<ast::TypeRef>) -> TypeRef {
490 TypeRef::from_ast_opt(&self.body_ctx, type_ref)
491 }
492
493 fn next_field_idx(&self) -> Idx<Field> {
494 Idx::from_raw(RawId::from(self.tree.fields.len() as u32))
495 }
496 fn next_variant_idx(&self) -> Idx<Variant> {
497 Idx::from_raw(RawId::from(self.tree.variants.len() as u32))
498 }
499}
500
501fn desugar_future_path(orig: TypeRef) -> Path {
502 let path = path![std::future::Future];
503 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
504 let mut last = GenericArgs::empty();
505 let binding =
506 AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() };
507 last.bindings.push(binding);
508 generic_args.push(Some(Arc::new(last)));
509
510 Path::from_known_path(path, generic_args)
511}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index af2a717c9..b5500f370 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -25,6 +25,8 @@ pub mod item_scope;
25pub mod dyn_map; 25pub mod dyn_map;
26pub mod keys; 26pub mod keys;
27 27
28pub mod item_tree;
29
28pub mod adt; 30pub mod adt;
29pub mod data; 31pub mod data;
30pub mod generics; 32pub mod generics;