diff options
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 150 |
1 files changed, 126 insertions, 24 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 9f8c6c4a5..fd7776fb7 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub(crate) mod src; | 3 | pub(crate) mod src; |
4 | pub(crate) mod docs; | ||
5 | pub(crate) mod attrs; | ||
6 | 4 | ||
7 | use std::sync::Arc; | 5 | use std::sync::Arc; |
8 | 6 | ||
@@ -10,18 +8,20 @@ use hir_def::{ | |||
10 | adt::VariantData, | 8 | adt::VariantData, |
11 | body::scope::ExprScopes, | 9 | body::scope::ExprScopes, |
12 | builtin_type::BuiltinType, | 10 | builtin_type::BuiltinType, |
13 | nameres::per_ns::PerNs, | 11 | docs::Documentation, |
12 | per_ns::PerNs, | ||
14 | resolver::{HasResolver, TypeNs}, | 13 | resolver::{HasResolver, TypeNs}, |
15 | type_ref::TypeRef, | 14 | type_ref::TypeRef, |
16 | ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, | 15 | ContainerId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, |
17 | ModuleId, UnionId, | 16 | LocalStructFieldId, Lookup, ModuleId, UnionId, |
18 | }; | 17 | }; |
19 | use hir_expand::{ | 18 | use hir_expand::{ |
20 | diagnostics::DiagnosticSink, | 19 | diagnostics::DiagnosticSink, |
21 | name::{self, AsName}, | 20 | name::{self, AsName}, |
21 | AstId, | ||
22 | }; | 22 | }; |
23 | use ra_db::{CrateId, Edition}; | 23 | use ra_db::{CrateId, Edition, FileId, FilePosition}; |
24 | use ra_syntax::ast; | 24 | use ra_syntax::{ast, AstNode, SyntaxNode}; |
25 | 25 | ||
26 | use crate::{ | 26 | use crate::{ |
27 | db::{DefDatabase, HirDatabase}, | 27 | db::{DefDatabase, HirDatabase}, |
@@ -31,7 +31,7 @@ use crate::{ | |||
31 | TypeAliasId, | 31 | TypeAliasId, |
32 | }, | 32 | }, |
33 | ty::{InferenceResult, Namespace, TraitRef}, | 33 | ty::{InferenceResult, Namespace, TraitRef}, |
34 | Either, HasSource, ImportId, Name, Source, Ty, | 34 | Either, HasSource, Name, Source, Ty, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | /// hir::Crate describes a single crate. It's the main interface with which | 37 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -79,6 +79,64 @@ impl Crate { | |||
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | pub enum ModuleSource { | ||
83 | SourceFile(ast::SourceFile), | ||
84 | Module(ast::Module), | ||
85 | } | ||
86 | |||
87 | impl ModuleSource { | ||
88 | pub fn new( | ||
89 | db: &impl DefDatabase, | ||
90 | file_id: Option<FileId>, | ||
91 | decl_id: Option<AstId<ast::Module>>, | ||
92 | ) -> ModuleSource { | ||
93 | match (file_id, decl_id) { | ||
94 | (Some(file_id), _) => { | ||
95 | let source_file = db.parse(file_id).tree(); | ||
96 | ModuleSource::SourceFile(source_file) | ||
97 | } | ||
98 | (None, Some(item_id)) => { | ||
99 | let module = item_id.to_node(db); | ||
100 | assert!(module.item_list().is_some(), "expected inline module"); | ||
101 | ModuleSource::Module(module) | ||
102 | } | ||
103 | (None, None) => panic!(), | ||
104 | } | ||
105 | } | ||
106 | |||
107 | // FIXME: this methods do not belong here | ||
108 | pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { | ||
109 | let parse = db.parse(position.file_id); | ||
110 | match &ra_syntax::algo::find_node_at_offset::<ast::Module>( | ||
111 | parse.tree().syntax(), | ||
112 | position.offset, | ||
113 | ) { | ||
114 | Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), | ||
115 | _ => { | ||
116 | let source_file = parse.tree(); | ||
117 | ModuleSource::SourceFile(source_file) | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | pub fn from_child_node(db: &impl DefDatabase, child: Source<&SyntaxNode>) -> ModuleSource { | ||
123 | if let Some(m) = | ||
124 | child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) | ||
125 | { | ||
126 | ModuleSource::Module(m) | ||
127 | } else { | ||
128 | let file_id = child.file_id.original_file(db); | ||
129 | let source_file = db.parse(file_id).tree(); | ||
130 | ModuleSource::SourceFile(source_file) | ||
131 | } | ||
132 | } | ||
133 | |||
134 | pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource { | ||
135 | let source_file = db.parse(file_id).tree(); | ||
136 | ModuleSource::SourceFile(source_file) | ||
137 | } | ||
138 | } | ||
139 | |||
82 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 140 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
83 | pub struct Module { | 141 | pub struct Module { |
84 | pub(crate) id: ModuleId, | 142 | pub(crate) id: ModuleId, |
@@ -110,10 +168,10 @@ impl_froms!( | |||
110 | BuiltinType | 168 | BuiltinType |
111 | ); | 169 | ); |
112 | 170 | ||
113 | pub use hir_def::ModuleSource; | 171 | pub use hir_def::attr::Attrs; |
114 | 172 | ||
115 | impl Module { | 173 | impl Module { |
116 | pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module { | 174 | pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { |
117 | Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } | 175 | Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } |
118 | } | 176 | } |
119 | 177 | ||
@@ -130,17 +188,6 @@ impl Module { | |||
130 | }) | 188 | }) |
131 | } | 189 | } |
132 | 190 | ||
133 | /// Returns the syntax of the last path segment corresponding to this import | ||
134 | pub fn import_source( | ||
135 | self, | ||
136 | db: &impl HirDatabase, | ||
137 | import: ImportId, | ||
138 | ) -> Either<ast::UseTree, ast::ExternCrateItem> { | ||
139 | let src = self.definition_source(db); | ||
140 | let (_, source_map) = db.raw_items_with_source_map(src.file_id); | ||
141 | source_map.get(&src.value, import) | ||
142 | } | ||
143 | |||
144 | /// Returns the crate this module is part of. | 191 | /// Returns the crate this module is part of. |
145 | pub fn krate(self) -> Crate { | 192 | pub fn krate(self) -> Crate { |
146 | Crate { crate_id: self.id.krate } | 193 | Crate { crate_id: self.id.krate } |
@@ -190,11 +237,13 @@ impl Module { | |||
190 | } | 237 | } |
191 | 238 | ||
192 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 239 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
193 | pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<ImportId>)> { | 240 | pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<Import>)> { |
194 | db.crate_def_map(self.id.krate)[self.id.module_id] | 241 | db.crate_def_map(self.id.krate)[self.id.module_id] |
195 | .scope | 242 | .scope |
196 | .entries() | 243 | .entries() |
197 | .map(|(name, res)| (name.clone(), res.def.into(), res.import)) | 244 | .map(|(name, res)| { |
245 | (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id })) | ||
246 | }) | ||
198 | .collect() | 247 | .collect() |
199 | } | 248 | } |
200 | 249 | ||
@@ -232,11 +281,16 @@ impl Module { | |||
232 | def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() | 281 | def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() |
233 | } | 282 | } |
234 | 283 | ||
235 | fn with_module_id(self, module_id: CrateModuleId) -> Module { | 284 | fn with_module_id(self, module_id: LocalModuleId) -> Module { |
236 | Module::new(self.krate(), module_id) | 285 | Module::new(self.krate(), module_id) |
237 | } | 286 | } |
238 | } | 287 | } |
239 | 288 | ||
289 | pub struct Import { | ||
290 | pub(crate) parent: Module, | ||
291 | pub(crate) id: LocalImportId, | ||
292 | } | ||
293 | |||
240 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 294 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
241 | pub struct StructField { | 295 | pub struct StructField { |
242 | pub(crate) parent: VariantDef, | 296 | pub(crate) parent: VariantDef, |
@@ -991,3 +1045,51 @@ impl From<PerNs> for ScopeDef { | |||
991 | .unwrap_or(ScopeDef::Unknown) | 1045 | .unwrap_or(ScopeDef::Unknown) |
992 | } | 1046 | } |
993 | } | 1047 | } |
1048 | |||
1049 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1050 | pub enum AttrDef { | ||
1051 | Module(Module), | ||
1052 | StructField(StructField), | ||
1053 | Adt(Adt), | ||
1054 | Function(Function), | ||
1055 | EnumVariant(EnumVariant), | ||
1056 | Static(Static), | ||
1057 | Const(Const), | ||
1058 | Trait(Trait), | ||
1059 | TypeAlias(TypeAlias), | ||
1060 | MacroDef(MacroDef), | ||
1061 | } | ||
1062 | |||
1063 | impl_froms!( | ||
1064 | AttrDef: Module, | ||
1065 | StructField, | ||
1066 | Adt(Struct, Enum, Union), | ||
1067 | EnumVariant, | ||
1068 | Static, | ||
1069 | Const, | ||
1070 | Function, | ||
1071 | Trait, | ||
1072 | TypeAlias, | ||
1073 | MacroDef | ||
1074 | ); | ||
1075 | |||
1076 | pub trait HasAttrs { | ||
1077 | fn attrs(self, db: &impl DefDatabase) -> Attrs; | ||
1078 | } | ||
1079 | |||
1080 | impl<T: Into<AttrDef>> HasAttrs for T { | ||
1081 | fn attrs(self, db: &impl DefDatabase) -> Attrs { | ||
1082 | let def: AttrDef = self.into(); | ||
1083 | db.attrs(def.into()) | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | pub trait Docs { | ||
1088 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>; | ||
1089 | } | ||
1090 | impl<T: Into<AttrDef> + Copy> Docs for T { | ||
1091 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> { | ||
1092 | let def: AttrDef = (*self).into(); | ||
1093 | db.documentation(def.into()) | ||
1094 | } | ||
1095 | } | ||