aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ra_hir_def/Cargo.toml1
-rw-r--r--crates/ra_hir_def/src/item_tree.rs235
3 files changed, 208 insertions, 29 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7bd2144a7..c2d00adeb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1018,6 +1018,7 @@ dependencies = [
1018 "ra_syntax", 1018 "ra_syntax",
1019 "ra_tt", 1019 "ra_tt",
1020 "rustc-hash", 1020 "rustc-hash",
1021 "smallvec",
1021 "stdx", 1022 "stdx",
1022 "test_utils", 1023 "test_utils",
1023] 1024]
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml
index ef1f65ee0..6d43924e3 100644
--- a/crates/ra_hir_def/Cargo.toml
+++ b/crates/ra_hir_def/Cargo.toml
@@ -17,6 +17,7 @@ drop_bomb = "0.1.4"
17fst = { version = "0.4", default-features = false } 17fst = { version = "0.4", default-features = false }
18itertools = "0.9.0" 18itertools = "0.9.0"
19indexmap = "1.4.0" 19indexmap = "1.4.0"
20smallvec = "1.4.0"
20 21
21stdx = { path = "../stdx" } 22stdx = { path = "../stdx" }
22 23
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs
index 7e81bc178..3ea6e10c9 100644
--- a/crates/ra_hir_def/src/item_tree.rs
+++ b/crates/ra_hir_def/src/item_tree.rs
@@ -4,7 +4,7 @@ use hir_expand::{
4 ast_id_map::{AstIdMap, FileAstId}, 4 ast_id_map::{AstIdMap, FileAstId},
5 hygiene::Hygiene, 5 hygiene::Hygiene,
6 name::{name, AsName, Name}, 6 name::{name, AsName, Name},
7 HirFileId, 7 HirFileId, InFile,
8}; 8};
9use ra_arena::{Arena, Idx, RawId}; 9use ra_arena::{Arena, Idx, RawId};
10use ra_syntax::{ast, match_ast}; 10use ra_syntax::{ast, match_ast};
@@ -12,17 +12,20 @@ use ra_syntax::{ast, match_ast};
12use crate::{ 12use crate::{
13 attr::Attrs, 13 attr::Attrs,
14 db::DefDatabase, 14 db::DefDatabase,
15 generics::GenericParams, 15 generics,
16 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path}, 16 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path},
17 type_ref::{Mutability, TypeBound, TypeRef}, 17 type_ref::{Mutability, TypeBound, TypeRef},
18 visibility::RawVisibility, 18 visibility::RawVisibility,
19}; 19};
20use ast::{AstNode, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; 20use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner};
21use either::Either;
22use smallvec::SmallVec;
21use std::{ 23use std::{
22 ops::{Index, Range}, 24 ops::{Index, Range},
23 sync::Arc, 25 sync::Arc,
24}; 26};
25 27
28/// The item tree of a source file.
26#[derive(Debug, Default, Eq, PartialEq)] 29#[derive(Debug, Default, Eq, PartialEq)]
27pub struct ItemTree { 30pub struct ItemTree {
28 top_level: Vec<ModItem>, 31 top_level: Vec<ModItem>,
@@ -70,6 +73,7 @@ impl ItemTree {
70 let ctx = Ctx { 73 let ctx = Ctx {
71 tree: ItemTree::default(), 74 tree: ItemTree::default(),
72 hygiene: Hygiene::new(db.upcast(), file_id), 75 hygiene: Hygiene::new(db.upcast(), file_id),
76 file: file_id,
73 source_ast_id_map: map, 77 source_ast_id_map: map,
74 body_ctx: crate::body::LowerCtx::new(db, file_id), 78 body_ctx: crate::body::LowerCtx::new(db, file_id),
75 }; 79 };
@@ -115,6 +119,7 @@ impl_index!(
115 exprs: Expr, 119 exprs: Expr,
116); 120);
117 121
122/// A desugared `extern crate` or `use` import.
118#[derive(Debug, Eq, PartialEq)] 123#[derive(Debug, Eq, PartialEq)]
119pub struct Import { 124pub struct Import {
120 pub path: ModPath, 125 pub path: ModPath,
@@ -131,11 +136,12 @@ pub struct Function {
131 pub name: Name, 136 pub name: Name,
132 pub attrs: Attrs, 137 pub attrs: Attrs,
133 pub visibility: RawVisibility, 138 pub visibility: RawVisibility,
134 pub generic_params: GenericParams, 139 pub generic_params: generics::GenericParams,
135 pub has_self_param: bool, 140 pub has_self_param: bool,
136 pub params: Vec<TypeRef>, 141 pub params: Vec<TypeRef>,
137 pub ret_type: TypeRef, 142 pub ret_type: TypeRef,
138 pub ast: FileAstId<ast::FnDef>, 143 pub ast: FileAstId<ast::FnDef>,
144 // FIXME inner items
139} 145}
140 146
141#[derive(Debug, Eq, PartialEq)] 147#[derive(Debug, Eq, PartialEq)]
@@ -143,7 +149,7 @@ pub struct Struct {
143 pub name: Name, 149 pub name: Name,
144 pub attrs: Attrs, 150 pub attrs: Attrs,
145 pub visibility: RawVisibility, 151 pub visibility: RawVisibility,
146 pub generic_params: GenericParams, 152 pub generic_params: generics::GenericParams,
147 pub fields: Fields, 153 pub fields: Fields,
148 pub ast: FileAstId<ast::StructDef>, 154 pub ast: FileAstId<ast::StructDef>,
149} 155}
@@ -153,7 +159,7 @@ pub struct Union {
153 pub name: Name, 159 pub name: Name,
154 pub attrs: Attrs, 160 pub attrs: Attrs,
155 pub visibility: RawVisibility, 161 pub visibility: RawVisibility,
156 pub generic_params: GenericParams, 162 pub generic_params: generics::GenericParams,
157 pub fields: Fields, 163 pub fields: Fields,
158} 164}
159 165
@@ -162,7 +168,7 @@ pub struct Enum {
162 pub name: Name, 168 pub name: Name,
163 pub attrs: Attrs, 169 pub attrs: Attrs,
164 pub visibility: RawVisibility, 170 pub visibility: RawVisibility,
165 pub generic_params: GenericParams, 171 pub generic_params: generics::GenericParams,
166 pub variants: Range<Idx<Variant>>, 172 pub variants: Range<Idx<Variant>>,
167} 173}
168 174
@@ -185,14 +191,14 @@ pub struct Static {
185pub struct Trait { 191pub struct Trait {
186 pub name: Name, 192 pub name: Name,
187 pub visibility: RawVisibility, 193 pub visibility: RawVisibility,
188 pub generic_params: GenericParams, 194 pub generic_params: generics::GenericParams,
189 pub auto: bool, 195 pub auto: bool,
190 pub items: Vec<AssocItem>, 196 pub items: Vec<AssocItem>,
191} 197}
192 198
193#[derive(Debug, Eq, PartialEq)] 199#[derive(Debug, Eq, PartialEq)]
194pub struct Impl { 200pub struct Impl {
195 pub generic_params: GenericParams, 201 pub generic_params: generics::GenericParams,
196 pub target_trait: Option<TypeRef>, 202 pub target_trait: Option<TypeRef>,
197 pub target_type: TypeRef, 203 pub target_type: TypeRef,
198 pub is_negative: bool, 204 pub is_negative: bool,
@@ -203,7 +209,7 @@ pub struct Impl {
203pub struct TypeAlias { 209pub struct TypeAlias {
204 pub name: Name, 210 pub name: Name,
205 pub visibility: RawVisibility, 211 pub visibility: RawVisibility,
206 pub generic_params: GenericParams, 212 pub generic_params: generics::GenericParams,
207 pub type_ref: Option<TypeRef>, 213 pub type_ref: Option<TypeRef>,
208} 214}
209 215
@@ -218,8 +224,12 @@ pub struct Mod {
218pub struct MacroCall { 224pub struct MacroCall {
219 pub name: Option<Name>, 225 pub name: Option<Name>,
220 pub path: ModPath, 226 pub path: ModPath,
221 pub export: bool, 227 /// Has `#[macro_export]`.
222 pub builtin: bool, 228 pub is_export: bool,
229 /// Has `#[macro_export(local_inner_macros)]`.
230 pub is_local_inner: bool,
231 /// Has `#[rustc_builtin_macro]`.
232 pub is_builtin: bool,
223 pub ast_id: FileAstId<ast::MacroCall>, 233 pub ast_id: FileAstId<ast::MacroCall>,
224} 234}
225 235
@@ -307,20 +317,36 @@ pub struct Field {
307 pub visibility: RawVisibility, 317 pub visibility: RawVisibility,
308} 318}
309 319
320struct ModItems(SmallVec<[ModItem; 1]>);
321
322impl<T> From<T> for ModItems
323where
324 T: Into<ModItem>,
325{
326 fn from(t: T) -> Self {
327 ModItems(SmallVec::from_buf([t.into(); 1]))
328 }
329}
330
310struct Ctx { 331struct Ctx {
311 tree: ItemTree, 332 tree: ItemTree,
312 hygiene: Hygiene, 333 hygiene: Hygiene,
334 file: HirFileId,
313 source_ast_id_map: Arc<AstIdMap>, 335 source_ast_id_map: Arc<AstIdMap>,
314 body_ctx: crate::body::LowerCtx, 336 body_ctx: crate::body::LowerCtx,
315} 337}
316 338
317impl Ctx { 339impl Ctx {
318 fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { 340 fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree {
319 self.tree.top_level = item_owner.items().flat_map(|item| self.lower_item(&item)).collect(); 341 self.tree.top_level = item_owner
342 .items()
343 .flat_map(|item| self.lower_mod_item(&item))
344 .flat_map(|items| items.0)
345 .collect();
320 self.tree 346 self.tree
321 } 347 }
322 348
323 fn lower_item(&mut self, item: &ast::ModuleItem) -> Option<ModItem> { 349 fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> {
324 match item { 350 match item {
325 ast::ModuleItem::StructDef(ast) => { 351 ast::ModuleItem::StructDef(ast) => {
326 self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) 352 self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into())
@@ -347,12 +373,48 @@ impl Ctx {
347 ast::ModuleItem::Module(ast) => { 373 ast::ModuleItem::Module(ast) => {
348 self.lower_module(ast).map(|data| self.tree.mods.alloc(data).into()) 374 self.lower_module(ast).map(|data| self.tree.mods.alloc(data).into())
349 } 375 }
350 ast::ModuleItem::TraitDef(_) => todo!(), 376 ast::ModuleItem::TraitDef(ast) => {
351 ast::ModuleItem::ImplDef(_) => todo!(), 377 self.lower_trait(ast).map(|data| self.tree.traits.alloc(data).into())
352 ast::ModuleItem::UseItem(_) => todo!(), 378 }
353 ast::ModuleItem::ExternCrateItem(_) => todo!(), 379 ast::ModuleItem::ImplDef(ast) => {
354 ast::ModuleItem::MacroCall(_) => todo!(), 380 self.lower_impl(ast).map(|data| self.tree.impls.alloc(data).into())
355 ast::ModuleItem::ExternBlock(_) => todo!(), 381 }
382 ast::ModuleItem::UseItem(ast) => Some(ModItems(
383 self.lower_use(ast)
384 .into_iter()
385 .map(|data| self.tree.imports.alloc(data).into())
386 .collect::<SmallVec<_>>(),
387 )),
388 ast::ModuleItem::ExternCrateItem(ast) => {
389 self.lower_extern_crate(ast).map(|data| self.tree.imports.alloc(data).into())
390 }
391 ast::ModuleItem::MacroCall(ast) => {
392 self.lower_macro_call(ast).map(|data| self.tree.macro_calls.alloc(data).into())
393 }
394 ast::ModuleItem::ExternBlock(ast) => Some(ModItems(
395 self.lower_extern_block(ast)
396 .into_iter()
397 .map(|item| match item {
398 Either::Left(func) => self.tree.functions.alloc(func).into(),
399 Either::Right(statik) => self.tree.statics.alloc(statik).into(),
400 })
401 .collect::<SmallVec<_>>(),
402 )),
403 }
404 }
405
406 fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> {
407 match item {
408 ast::AssocItem::FnDef(ast) => {
409 self.lower_function(ast).map(|data| self.tree.functions.alloc(data).into())
410 }
411 ast::AssocItem::TypeAliasDef(ast) => {
412 self.lower_type_alias(ast).map(|data| self.tree.type_aliases.alloc(data).into())
413 }
414 ast::AssocItem::ConstDef(ast) => {
415 let data = self.lower_const(ast);
416 Some(self.tree.consts.alloc(data).into())
417 }
356 } 418 }
357 } 419 }
358 420
@@ -385,7 +447,7 @@ impl Ctx {
385 let start = self.next_field_idx(); 447 let start = self.next_field_idx();
386 for field in fields.fields() { 448 for field in fields.fields() {
387 if let Some(data) = self.lower_record_field(&field) { 449 if let Some(data) = self.lower_record_field(&field) {
388 let idx = self.tree.fields.alloc(data); 450 self.tree.fields.alloc(data);
389 } 451 }
390 } 452 }
391 let end = self.next_field_idx(); 453 let end = self.next_field_idx();
@@ -404,7 +466,7 @@ impl Ctx {
404 let start = self.next_field_idx(); 466 let start = self.next_field_idx();
405 for (i, field) in fields.fields().enumerate() { 467 for (i, field) in fields.fields().enumerate() {
406 if let Some(data) = self.lower_tuple_field(i, &field) { 468 if let Some(data) = self.lower_tuple_field(i, &field) {
407 let idx = self.tree.fields.alloc(data); 469 self.tree.fields.alloc(data);
408 } 470 }
409 } 471 }
410 let end = self.next_field_idx(); 472 let end = self.next_field_idx();
@@ -451,7 +513,7 @@ impl Ctx {
451 let start = self.next_variant_idx(); 513 let start = self.next_variant_idx();
452 for variant in variants.variants() { 514 for variant in variants.variants() {
453 if let Some(data) = self.lower_variant(&variant) { 515 if let Some(data) = self.lower_variant(&variant) {
454 let idx = self.tree.variants.alloc(data); 516 self.tree.variants.alloc(data);
455 } 517 }
456 } 518 }
457 let end = self.next_variant_idx(); 519 let end = self.next_variant_idx();
@@ -551,14 +613,129 @@ impl Ctx {
551 fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { 613 fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> {
552 let name = module.name()?.as_name(); 614 let name = module.name()?.as_name();
553 let visibility = self.lower_visibility(module); 615 let visibility = self.lower_visibility(module);
554 let items = module 616 let items = module.item_list().map(move |list| {
555 .item_list() 617 list.items()
556 .map(move |list| list.items().flat_map(move |item| self.lower_item(&item)).collect()); 618 .flat_map(move |item| self.lower_mod_item(&item))
619 .flat_map(|items| items.0)
620 .collect()
621 });
557 Some(Mod { name, visibility, items: items.unwrap_or_default() }) 622 Some(Mod { name, visibility, items: items.unwrap_or_default() })
558 } 623 }
559 624
560 fn lower_generic_params(&mut self, _item: &impl ast::TypeParamsOwner) -> GenericParams { 625 fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> {
561 None.unwrap() 626 let name = trait_def.name()?.as_name();
627 let visibility = self.lower_visibility(trait_def);
628 let generic_params = self.lower_generic_params(trait_def);
629 let auto = trait_def.auto_token().is_some();
630 let items = trait_def.item_list().map(move |list| {
631 // FIXME: Does not handle macros
632 list.assoc_items().flat_map(move |item| self.lower_assoc_item(&item)).collect()
633 });
634 Some(Trait { name, visibility, generic_params, auto, items: items.unwrap_or_default() })
635 }
636
637 fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> {
638 let generic_params = self.lower_generic_params(impl_def);
639 let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr));
640 let target_type = self.lower_type_ref(&impl_def.target_type()?);
641 let is_negative = impl_def.excl_token().is_some();
642 let items = impl_def
643 .item_list()?
644 .assoc_items()
645 .filter_map(|item| self.lower_assoc_item(&item))
646 .collect();
647 Some(Impl { generic_params, target_trait, target_type, is_negative, items })
648 }
649
650 fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> {
651 // FIXME: cfg_attr
652 let is_prelude = use_item.has_atom_attr("prelude_import");
653 let visibility = self.lower_visibility(use_item);
654
655 // Every use item can expand to many `Import`s.
656 let mut imports = Vec::new();
657 ModPath::expand_use_item(
658 InFile::new(self.file, use_item.clone()),
659 &self.hygiene,
660 |path, _tree, is_glob, alias| {
661 imports.push(Import {
662 path,
663 alias,
664 visibility: visibility.clone(),
665 is_glob,
666 is_prelude,
667 is_extern_crate: false,
668 is_macro_use: false,
669 });
670 },
671 );
672
673 imports
674 }
675
676 fn lower_extern_crate(&mut self, extern_crate: &ast::ExternCrateItem) -> Option<Import> {
677 let path = ModPath::from_name_ref(&extern_crate.name_ref()?);
678 let alias = extern_crate.alias().map(|a| {
679 a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
680 });
681 let visibility = self.lower_visibility(extern_crate);
682 // FIXME: cfg_attr
683 let is_macro_use = extern_crate.has_atom_attr("macro_use");
684
685 Some(Import {
686 path,
687 alias,
688 visibility,
689 is_glob: false,
690 is_prelude: false,
691 is_extern_crate: true,
692 is_macro_use,
693 })
694 }
695
696 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<MacroCall> {
697 let name = m.name().map(|it| it.as_name());
698 let attrs = Attrs::new(m, &self.hygiene);
699 let path = ModPath::from_src(m.path()?, &self.hygiene)?;
700
701 let ast_id = self.source_ast_id_map.ast_id(m);
702
703 // FIXME: cfg_attr
704 let export_attr = attrs.by_key("macro_export");
705
706 let is_export = export_attr.exists();
707 let is_local_inner = if is_export {
708 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
709 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
710 ident.text.contains("local_inner_macros")
711 }
712 _ => false,
713 })
714 } else {
715 false
716 };
717
718 let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
719 Some(MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id })
720 }
721
722 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<Either<Function, Static>> {
723 block.extern_item_list().map_or(Vec::new(), |list| {
724 list.extern_items()
725 .filter_map(|item| match item {
726 ast::ExternItem::FnDef(ast) => self.lower_function(&ast).map(Either::Left),
727 ast::ExternItem::StaticDef(ast) => self.lower_static(&ast).map(Either::Right),
728 })
729 .collect()
730 })
731 }
732
733 fn lower_generic_params(
734 &mut self,
735 _item: &impl ast::TypeParamsOwner,
736 ) -> generics::GenericParams {
737 // TODO
738 generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() }
562 } 739 }
563 740
564 fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 741 fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
@@ -583,7 +760,7 @@ impl Ctx {
583} 760}
584 761
585fn desugar_future_path(orig: TypeRef) -> Path { 762fn desugar_future_path(orig: TypeRef) -> Path {
586 let path = path![std::future::Future]; 763 let path = path![core::future::Future];
587 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); 764 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
588 let mut last = GenericArgs::empty(); 765 let mut last = GenericArgs::empty();
589 let binding = 766 let binding =