]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir/src/has_source.rs
Revert "Merge #2629"
[rust.git] / crates / ra_hir / src / has_source.rs
1 //! FIXME: write short doc here
2
3 use either::Either;
4 use hir_def::{
5     nameres::ModuleSource,
6     src::{HasChildSource, HasSource as _},
7     Lookup, VariantId,
8 };
9 use ra_syntax::ast;
10
11 use crate::{
12     db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef,
13     Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
14 };
15
16 pub use hir_expand::InFile;
17
18 pub trait HasSource {
19     type Ast;
20     fn source(self, db: &impl DefDatabase) -> InFile<Self::Ast>;
21 }
22
23 /// NB: Module is !HasSource, because it has two source nodes at the same time:
24 /// definition and declaration.
25 impl Module {
26     /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
27     pub fn definition_source(self, db: &impl DefDatabase) -> InFile<ModuleSource> {
28         let def_map = db.crate_def_map(self.id.krate);
29         def_map[self.id.local_id].definition_source(db)
30     }
31
32     /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
33     /// `None` for the crate root.
34     pub fn declaration_source(self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
35         let def_map = db.crate_def_map(self.id.krate);
36         def_map[self.id.local_id].declaration_source(db)
37     }
38 }
39
40 impl HasSource for StructField {
41     type Ast = FieldSource;
42     fn source(self, db: &impl DefDatabase) -> InFile<FieldSource> {
43         let var = VariantId::from(self.parent);
44         let src = var.child_source(db);
45         src.map(|it| match it[self.id].clone() {
46             Either::Left(it) => FieldSource::Pos(it),
47             Either::Right(it) => FieldSource::Named(it),
48         })
49     }
50 }
51 impl HasSource for Struct {
52     type Ast = ast::StructDef;
53     fn source(self, db: &impl DefDatabase) -> InFile<ast::StructDef> {
54         self.id.lookup(db).source(db)
55     }
56 }
57 impl HasSource for Union {
58     type Ast = ast::UnionDef;
59     fn source(self, db: &impl DefDatabase) -> InFile<ast::UnionDef> {
60         self.id.lookup(db).source(db)
61     }
62 }
63 impl HasSource for Enum {
64     type Ast = ast::EnumDef;
65     fn source(self, db: &impl DefDatabase) -> InFile<ast::EnumDef> {
66         self.id.lookup(db).source(db)
67     }
68 }
69 impl HasSource for EnumVariant {
70     type Ast = ast::EnumVariant;
71     fn source(self, db: &impl DefDatabase) -> InFile<ast::EnumVariant> {
72         self.parent.id.child_source(db).map(|map| map[self.id].clone())
73     }
74 }
75 impl HasSource for Function {
76     type Ast = ast::FnDef;
77     fn source(self, db: &impl DefDatabase) -> InFile<ast::FnDef> {
78         self.id.lookup(db).source(db)
79     }
80 }
81 impl HasSource for Const {
82     type Ast = ast::ConstDef;
83     fn source(self, db: &impl DefDatabase) -> InFile<ast::ConstDef> {
84         self.id.lookup(db).source(db)
85     }
86 }
87 impl HasSource for Static {
88     type Ast = ast::StaticDef;
89     fn source(self, db: &impl DefDatabase) -> InFile<ast::StaticDef> {
90         self.id.lookup(db).source(db)
91     }
92 }
93 impl HasSource for Trait {
94     type Ast = ast::TraitDef;
95     fn source(self, db: &impl DefDatabase) -> InFile<ast::TraitDef> {
96         self.id.lookup(db).source(db)
97     }
98 }
99 impl HasSource for TypeAlias {
100     type Ast = ast::TypeAliasDef;
101     fn source(self, db: &impl DefDatabase) -> InFile<ast::TypeAliasDef> {
102         self.id.lookup(db).source(db)
103     }
104 }
105 impl HasSource for MacroDef {
106     type Ast = ast::MacroCall;
107     fn source(self, db: &impl DefDatabase) -> InFile<ast::MacroCall> {
108         InFile {
109             file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id,
110             value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db),
111         }
112     }
113 }
114 impl HasSource for ImplBlock {
115     type Ast = ast::ImplBlock;
116     fn source(self, db: &impl DefDatabase) -> InFile<ast::ImplBlock> {
117         self.id.lookup(db).source(db)
118     }
119 }
120 impl HasSource for Import {
121     type Ast = Either<ast::UseTree, ast::ExternCrateItem>;
122
123     /// Returns the syntax of the last path segment corresponding to this import
124     fn source(self, db: &impl DefDatabase) -> InFile<Self::Ast> {
125         let src = self.parent.definition_source(db);
126         let (_, source_map) = db.raw_items_with_source_map(src.file_id);
127         let root = db.parse_or_expand(src.file_id).unwrap();
128         let ptr = source_map.get(self.id);
129         src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root)))
130     }
131 }
132
133 impl HasSource for TypeParam {
134     type Ast = Either<ast::TraitDef, ast::TypeParam>;
135     fn source(self, db: &impl DefDatabase) -> InFile<Self::Ast> {
136         let child_source = self.id.parent.child_source(db);
137         child_source.map(|it| it[self.id.local_id].clone())
138     }
139 }