aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs150
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
3pub(crate) mod src; 3pub(crate) mod src;
4pub(crate) mod docs;
5pub(crate) mod attrs;
6 4
7use std::sync::Arc; 5use 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};
19use hir_expand::{ 18use hir_expand::{
20 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
21 name::{self, AsName}, 20 name::{self, AsName},
21 AstId,
22}; 22};
23use ra_db::{CrateId, Edition}; 23use ra_db::{CrateId, Edition, FileId, FilePosition};
24use ra_syntax::ast; 24use ra_syntax::{ast, AstNode, SyntaxNode};
25 25
26use crate::{ 26use 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
82pub enum ModuleSource {
83 SourceFile(ast::SourceFile),
84 Module(ast::Module),
85}
86
87impl 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)]
83pub struct Module { 141pub 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
113pub use hir_def::ModuleSource; 171pub use hir_def::attr::Attrs;
114 172
115impl Module { 173impl 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
289pub 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)]
241pub struct StructField { 295pub 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)]
1050pub 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
1063impl_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
1076pub trait HasAttrs {
1077 fn attrs(self, db: &impl DefDatabase) -> Attrs;
1078}
1079
1080impl<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
1087pub trait Docs {
1088 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
1089}
1090impl<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}