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.rs305
1 files changed, 144 insertions, 161 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 5690040a7..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,29 +8,30 @@ 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 traits::TraitData, 14 type_ref::TypeRef,
16 type_ref::{Mutability, TypeRef}, 15 ContainerId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId,
17 ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, 16 LocalStructFieldId, Lookup, ModuleId, UnionId,
18 ModuleId, UnionId,
19}; 17};
20use hir_expand::{ 18use hir_expand::{
21 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
22 name::{self, AsName}, 20 name::{self, AsName},
21 AstId,
23}; 22};
24use ra_db::{CrateId, Edition}; 23use ra_db::{CrateId, Edition, FileId, FilePosition};
25use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 24use ra_syntax::{ast, AstNode, SyntaxNode};
26 25
27use crate::{ 26use crate::{
28 db::{AstDatabase, DefDatabase, HirDatabase}, 27 db::{DefDatabase, HirDatabase},
29 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
30 ids::{ 29 ids::{
31 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, 30 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId,
32 TypeAliasId, 31 TypeAliasId,
33 }, 32 },
34 ty::{InferenceResult, Namespace, TraitRef}, 33 ty::{InferenceResult, Namespace, TraitRef},
35 Either, HasSource, ImportId, Name, Source, Ty, 34 Either, HasSource, Name, Source, Ty,
36}; 35};
37 36
38/// 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
@@ -80,6 +79,64 @@ impl Crate {
80 } 79 }
81} 80}
82 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
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
84pub struct Module { 141pub struct Module {
85 pub(crate) id: ModuleId, 142 pub(crate) id: ModuleId,
@@ -111,10 +168,10 @@ impl_froms!(
111 BuiltinType 168 BuiltinType
112); 169);
113 170
114pub use hir_def::ModuleSource; 171pub use hir_def::attr::Attrs;
115 172
116impl Module { 173impl Module {
117 pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module { 174 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
118 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 } }
119 } 176 }
120 177
@@ -131,17 +188,6 @@ impl Module {
131 }) 188 })
132 } 189 }
133 190
134 /// Returns the syntax of the last path segment corresponding to this import
135 pub fn import_source(
136 self,
137 db: &impl HirDatabase,
138 import: ImportId,
139 ) -> Either<ast::UseTree, ast::ExternCrateItem> {
140 let src = self.definition_source(db);
141 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
142 source_map.get(&src.value, import)
143 }
144
145 /// Returns the crate this module is part of. 191 /// Returns the crate this module is part of.
146 pub fn krate(self) -> Crate { 192 pub fn krate(self) -> Crate {
147 Crate { crate_id: self.id.krate } 193 Crate { crate_id: self.id.krate }
@@ -191,11 +237,13 @@ impl Module {
191 } 237 }
192 238
193 /// Returns a `ModuleScope`: a set of items, visible in this module. 239 /// Returns a `ModuleScope`: a set of items, visible in this module.
194 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>)> {
195 db.crate_def_map(self.id.krate)[self.id.module_id] 241 db.crate_def_map(self.id.krate)[self.id.module_id]
196 .scope 242 .scope
197 .entries() 243 .entries()
198 .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 })
199 .collect() 247 .collect()
200 } 248 }
201 249
@@ -233,11 +281,16 @@ impl Module {
233 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()
234 } 282 }
235 283
236 fn with_module_id(self, module_id: CrateModuleId) -> Module { 284 fn with_module_id(self, module_id: LocalModuleId) -> Module {
237 Module::new(self.krate(), module_id) 285 Module::new(self.krate(), module_id)
238 } 286 }
239} 287}
240 288
289pub struct Import {
290 pub(crate) parent: Module,
291 pub(crate) id: LocalImportId,
292}
293
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242pub struct StructField { 295pub struct StructField {
243 pub(crate) parent: VariantDef, 296 pub(crate) parent: VariantDef,
@@ -561,77 +614,6 @@ pub struct Function {
561 pub(crate) id: FunctionId, 614 pub(crate) id: FunctionId,
562} 615}
563 616
564#[derive(Debug, Clone, PartialEq, Eq)]
565pub struct FnData {
566 pub(crate) name: Name,
567 pub(crate) params: Vec<TypeRef>,
568 pub(crate) ret_type: TypeRef,
569 /// True if the first param is `self`. This is relevant to decide whether this
570 /// can be called as a method.
571 pub(crate) has_self_param: bool,
572}
573
574impl FnData {
575 pub(crate) fn fn_data_query(
576 db: &(impl DefDatabase + AstDatabase),
577 func: Function,
578 ) -> Arc<FnData> {
579 let src = func.source(db);
580 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
581 let mut params = Vec::new();
582 let mut has_self_param = false;
583 if let Some(param_list) = src.value.param_list() {
584 if let Some(self_param) = param_list.self_param() {
585 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
586 TypeRef::from_ast(type_ref)
587 } else {
588 let self_type = TypeRef::Path(name::SELF_TYPE.into());
589 match self_param.kind() {
590 ast::SelfParamKind::Owned => self_type,
591 ast::SelfParamKind::Ref => {
592 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
593 }
594 ast::SelfParamKind::MutRef => {
595 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
596 }
597 }
598 };
599 params.push(self_type);
600 has_self_param = true;
601 }
602 for param in param_list.params() {
603 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
604 params.push(type_ref);
605 }
606 }
607 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
608 TypeRef::from_ast(type_ref)
609 } else {
610 TypeRef::unit()
611 };
612
613 let sig = FnData { name, params, ret_type, has_self_param };
614 Arc::new(sig)
615 }
616 pub fn name(&self) -> &Name {
617 &self.name
618 }
619
620 pub fn params(&self) -> &[TypeRef] {
621 &self.params
622 }
623
624 pub fn ret_type(&self) -> &TypeRef {
625 &self.ret_type
626 }
627
628 /// True if the first arg is `self`. This is relevant to decide whether this
629 /// can be called as a method.
630 pub fn has_self_param(&self) -> bool {
631 self.has_self_param
632 }
633}
634
635impl Function { 617impl Function {
636 pub fn module(self, db: &impl DefDatabase) -> Module { 618 pub fn module(self, db: &impl DefDatabase) -> Module {
637 self.id.lookup(db).module(db).into() 619 self.id.lookup(db).module(db).into()
@@ -642,7 +624,15 @@ impl Function {
642 } 624 }
643 625
644 pub fn name(self, db: &impl HirDatabase) -> Name { 626 pub fn name(self, db: &impl HirDatabase) -> Name {
645 self.data(db).name.clone() 627 db.function_data(self.id).name.clone()
628 }
629
630 pub fn has_self_param(self, db: &impl HirDatabase) -> bool {
631 db.function_data(self.id).has_self_param
632 }
633
634 pub fn params(self, db: &impl HirDatabase) -> Vec<TypeRef> {
635 db.function_data(self.id).params.clone()
646 } 636 }
647 637
648 pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 638 pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
@@ -657,10 +647,6 @@ impl Function {
657 db.type_for_def(self.into(), Namespace::Values) 647 db.type_for_def(self.into(), Namespace::Values)
658 } 648 }
659 649
660 pub fn data(self, db: &impl HirDatabase) -> Arc<FnData> {
661 db.fn_data(self)
662 }
663
664 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 650 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
665 db.infer(self.into()) 651 db.infer(self.into())
666 } 652 }
@@ -711,12 +697,8 @@ impl Const {
711 Some(self.module(db).krate()) 697 Some(self.module(db).krate())
712 } 698 }
713 699
714 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
715 db.const_data(self)
716 }
717
718 pub fn name(self, db: &impl HirDatabase) -> Option<Name> { 700 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
719 self.data(db).name().cloned() 701 db.const_data(self.id).name.clone()
720 } 702 }
721 703
722 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 704 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
@@ -748,45 +730,6 @@ impl Const {
748 } 730 }
749} 731}
750 732
751#[derive(Debug, Clone, PartialEq, Eq)]
752pub struct ConstData {
753 pub(crate) name: Option<Name>,
754 pub(crate) type_ref: TypeRef,
755}
756
757impl ConstData {
758 pub fn name(&self) -> Option<&Name> {
759 self.name.as_ref()
760 }
761
762 pub fn type_ref(&self) -> &TypeRef {
763 &self.type_ref
764 }
765
766 pub(crate) fn const_data_query(
767 db: &(impl DefDatabase + AstDatabase),
768 konst: Const,
769 ) -> Arc<ConstData> {
770 let node = konst.source(db).value;
771 const_data_for(&node)
772 }
773
774 pub(crate) fn static_data_query(
775 db: &(impl DefDatabase + AstDatabase),
776 konst: Static,
777 ) -> Arc<ConstData> {
778 let node = konst.source(db).value;
779 const_data_for(&node)
780 }
781}
782
783fn const_data_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstData> {
784 let name = node.name().map(|n| n.as_name());
785 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
786 let sig = ConstData { name, type_ref };
787 Arc::new(sig)
788}
789
790#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 733#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
791pub struct Static { 734pub struct Static {
792 pub(crate) id: StaticId, 735 pub(crate) id: StaticId,
@@ -801,10 +744,6 @@ impl Static {
801 Some(self.module(db).krate()) 744 Some(self.module(db).krate())
802 } 745 }
803 746
804 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
805 db.static_data(self)
806 }
807
808 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 747 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
809 db.infer(self.into()) 748 db.infer(self.into())
810 } 749 }
@@ -821,11 +760,11 @@ impl Trait {
821 } 760 }
822 761
823 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 762 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
824 self.trait_data(db).name.clone() 763 db.trait_data(self.id).name.clone()
825 } 764 }
826 765
827 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 766 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
828 self.trait_data(db).items.iter().map(|it| (*it).into()).collect() 767 db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect()
829 } 768 }
830 769
831 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { 770 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
@@ -871,7 +810,7 @@ impl Trait {
871 } 810 }
872 811
873 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { 812 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
874 let trait_data = self.trait_data(db); 813 let trait_data = db.trait_data(self.id);
875 let res = 814 let res =
876 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?; 815 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?;
877 Some(res) 816 Some(res)
@@ -885,16 +824,12 @@ impl Trait {
885 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name)) 824 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
886 } 825 }
887 826
888 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
889 db.trait_data(self.id)
890 }
891
892 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { 827 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
893 TraitRef::for_trait(db, self) 828 TraitRef::for_trait(db, self)
894 } 829 }
895 830
896 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 831 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
897 self.trait_data(db).auto 832 db.trait_data(self.id).auto
898 } 833 }
899} 834}
900 835
@@ -937,7 +872,7 @@ impl TypeAlias {
937 } 872 }
938 873
939 pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> { 874 pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> {
940 db.type_alias_data(self).type_ref.clone() 875 db.type_alias_data(self.id).type_ref.clone()
941 } 876 }
942 877
943 pub fn ty(self, db: &impl HirDatabase) -> Ty { 878 pub fn ty(self, db: &impl HirDatabase) -> Ty {
@@ -945,7 +880,7 @@ impl TypeAlias {
945 } 880 }
946 881
947 pub fn name(self, db: &impl DefDatabase) -> Name { 882 pub fn name(self, db: &impl DefDatabase) -> Name {
948 db.type_alias_data(self).name.clone() 883 db.type_alias_data(self.id).name.clone()
949 } 884 }
950} 885}
951 886
@@ -1110,3 +1045,51 @@ impl From<PerNs> for ScopeDef {
1110 .unwrap_or(ScopeDef::Unknown) 1045 .unwrap_or(ScopeDef::Unknown)
1111 } 1046 }
1112} 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}