diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 66 | ||||
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 12 |
5 files changed, 90 insertions, 50 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 45e31095c..c5cfd875f 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | docs::Documentation, | 10 | docs::Documentation, |
11 | expr::{BindingAnnotation, Pat, PatId}, | 11 | expr::{BindingAnnotation, Pat, PatId}, |
12 | per_ns::PerNs, | 12 | per_ns::PerNs, |
13 | resolver::HasResolver, | 13 | resolver::{HasResolver, Resolver}, |
14 | type_ref::{Mutability, TypeRef}, | 14 | type_ref::{Mutability, TypeRef}, |
15 | AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, | 15 | AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, |
16 | ImplId, LocalEnumVariantId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, | 16 | ImplId, LocalEnumVariantId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, |
@@ -33,7 +33,11 @@ use ra_syntax::{ | |||
33 | }; | 33 | }; |
34 | use rustc_hash::FxHashSet; | 34 | use rustc_hash::FxHashSet; |
35 | 35 | ||
36 | use crate::{db::HirDatabase, has_source::HasSource, CallableDef, HirDisplay, InFile, Name}; | 36 | use crate::{ |
37 | db::{DefDatabase, HirDatabase}, | ||
38 | has_source::HasSource, | ||
39 | CallableDef, HirDisplay, InFile, Name, | ||
40 | }; | ||
37 | 41 | ||
38 | /// hir::Crate describes a single crate. It's the main interface with which | 42 | /// hir::Crate describes a single crate. It's the main interface with which |
39 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the | 43 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the |
@@ -274,20 +278,10 @@ impl Module { | |||
274 | /// this module, if possible. | 278 | /// this module, if possible. |
275 | pub fn find_use_path( | 279 | pub fn find_use_path( |
276 | self, | 280 | self, |
277 | db: &dyn HirDatabase, | 281 | db: &dyn DefDatabase, |
278 | item: ModuleDef, | 282 | item: impl Into<ItemInNs>, |
279 | ) -> Option<hir_def::path::ModPath> { | 283 | ) -> Option<hir_def::path::ModPath> { |
280 | // FIXME expose namespace choice | 284 | hir_def::find_path::find_path(db, item.into(), self.into()) |
281 | hir_def::find_path::find_path(db.upcast(), determine_item_namespace(item), self.into()) | ||
282 | } | ||
283 | } | ||
284 | |||
285 | fn determine_item_namespace(module_def: ModuleDef) -> ItemInNs { | ||
286 | match module_def { | ||
287 | ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => { | ||
288 | ItemInNs::Values(module_def.into()) | ||
289 | } | ||
290 | _ => ItemInNs::Types(module_def.into()), | ||
291 | } | 285 | } |
292 | } | 286 | } |
293 | 287 | ||
@@ -912,10 +906,8 @@ impl Local { | |||
912 | let def = DefWithBodyId::from(self.parent); | 906 | let def = DefWithBodyId::from(self.parent); |
913 | let infer = db.infer(def); | 907 | let infer = db.infer(def); |
914 | let ty = infer[self.pat_id].clone(); | 908 | let ty = infer[self.pat_id].clone(); |
915 | let resolver = def.resolver(db.upcast()); | ||
916 | let krate = def.module(db.upcast()).krate; | 909 | let krate = def.module(db.upcast()).krate; |
917 | let environment = TraitEnvironment::lower(db, &resolver); | 910 | Type::new(db, krate, def, ty) |
918 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
919 | } | 911 | } |
920 | 912 | ||
921 | pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::BindPat, ast::SelfParam>> { | 913 | pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::BindPat, ast::SelfParam>> { |
@@ -1020,11 +1012,21 @@ impl ImplDef { | |||
1020 | 1012 | ||
1021 | #[derive(Clone, PartialEq, Eq, Debug)] | 1013 | #[derive(Clone, PartialEq, Eq, Debug)] |
1022 | pub struct Type { | 1014 | pub struct Type { |
1023 | pub(crate) krate: CrateId, | 1015 | krate: CrateId, |
1024 | pub(crate) ty: InEnvironment<Ty>, | 1016 | ty: InEnvironment<Ty>, |
1025 | } | 1017 | } |
1026 | 1018 | ||
1027 | impl Type { | 1019 | impl Type { |
1020 | pub(crate) fn new_with_resolver( | ||
1021 | db: &dyn HirDatabase, | ||
1022 | resolver: &Resolver, | ||
1023 | ty: Ty, | ||
1024 | ) -> Option<Type> { | ||
1025 | let krate = resolver.krate()?; | ||
1026 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1027 | Some(Type { krate, ty: InEnvironment { value: ty, environment } }) | ||
1028 | } | ||
1029 | |||
1028 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { | 1030 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { |
1029 | let resolver = lexical_env.resolver(db.upcast()); | 1031 | let resolver = lexical_env.resolver(db.upcast()); |
1030 | let environment = TraitEnvironment::lower(db, &resolver); | 1032 | let environment = TraitEnvironment::lower(db, &resolver); |
@@ -1042,30 +1044,18 @@ impl Type { | |||
1042 | } | 1044 | } |
1043 | 1045 | ||
1044 | pub fn is_bool(&self) -> bool { | 1046 | pub fn is_bool(&self) -> bool { |
1045 | match &self.ty.value { | 1047 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) |
1046 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
1047 | TypeCtor::Bool => true, | ||
1048 | _ => false, | ||
1049 | }, | ||
1050 | _ => false, | ||
1051 | } | ||
1052 | } | 1048 | } |
1053 | 1049 | ||
1054 | pub fn is_mutable_reference(&self) -> bool { | 1050 | pub fn is_mutable_reference(&self) -> bool { |
1055 | match &self.ty.value { | 1051 | matches!( |
1056 | Ty::Apply(a_ty) => match a_ty.ctor { | 1052 | self.ty.value, |
1057 | TypeCtor::Ref(Mutability::Mut) => true, | 1053 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. }) |
1058 | _ => false, | 1054 | ) |
1059 | }, | ||
1060 | _ => false, | ||
1061 | } | ||
1062 | } | 1055 | } |
1063 | 1056 | ||
1064 | pub fn is_unknown(&self) -> bool { | 1057 | pub fn is_unknown(&self) -> bool { |
1065 | match &self.ty.value { | 1058 | matches!(self.ty.value, Ty::Unknown) |
1066 | Ty::Unknown => true, | ||
1067 | _ => false, | ||
1068 | } | ||
1069 | } | 1059 | } |
1070 | 1060 | ||
1071 | /// Checks that particular type `ty` implements `std::future::Future`. | 1061 | /// Checks that particular type `ty` implements `std::future::Future`. |
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index c179b13c6..62fb52e72 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs | |||
@@ -9,8 +9,8 @@ use hir_def::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | Adt, AssocItem, AttrDef, DefWithBody, EnumVariant, GenericDef, Local, ModuleDef, StructField, | 12 | code_model::ItemInNs, Adt, AssocItem, AttrDef, DefWithBody, EnumVariant, GenericDef, Local, |
13 | VariantDef, | 13 | MacroDef, ModuleDef, StructField, VariantDef, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | macro_rules! from_id { | 16 | macro_rules! from_id { |
@@ -228,3 +228,20 @@ impl From<(DefWithBodyId, PatId)> for Local { | |||
228 | Local { parent, pat_id } | 228 | Local { parent, pat_id } |
229 | } | 229 | } |
230 | } | 230 | } |
231 | |||
232 | impl From<MacroDef> for ItemInNs { | ||
233 | fn from(macro_def: MacroDef) -> Self { | ||
234 | ItemInNs::Macros(macro_def.into()) | ||
235 | } | ||
236 | } | ||
237 | |||
238 | impl From<ModuleDef> for ItemInNs { | ||
239 | fn from(module_def: ModuleDef) -> Self { | ||
240 | match module_def { | ||
241 | ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => { | ||
242 | ItemInNs::Values(module_def.into()) | ||
243 | } | ||
244 | _ => ItemInNs::Types(module_def.into()), | ||
245 | } | ||
246 | } | ||
247 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9f59d590c..713d45f48 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -4,6 +4,18 @@ | |||
4 | //! The principal difference between HIR and syntax trees is that HIR is bound | 4 | //! The principal difference between HIR and syntax trees is that HIR is bound |
5 | //! to a particular crate instance. That is, it has cfg flags and features | 5 | //! to a particular crate instance. That is, it has cfg flags and features |
6 | //! applied. So, the relation between syntax and HIR is many-to-one. | 6 | //! applied. So, the relation between syntax and HIR is many-to-one. |
7 | //! | ||
8 | //! HIR is the public API of the all of the compiler logic above syntax trees. | ||
9 | //! It is written in "OO" style. Each type is self contained (as in, it knows it's | ||
10 | //! parents and full context). It should be "clean code". | ||
11 | //! | ||
12 | //! `ra_hir_*` crates are the implementation of the compiler logic. | ||
13 | //! They are written in "ECS" style, with relatively little abstractions. | ||
14 | //! Many types are not self-contained, and explicitly use local indexes, arenas, etc. | ||
15 | //! | ||
16 | //! `ra_hir` is what insulates the "we don't know how to actually write an incremental compiler" | ||
17 | //! from the ide with completions, hovers, etc. It is a (soft, internal) boundary: | ||
18 | //! https://www.tedinski.com/2018/02/06/system-boundaries.html. | ||
7 | 19 | ||
8 | #![recursion_limit = "512"] | 20 | #![recursion_limit = "512"] |
9 | 21 | ||
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 55e634528..d982f6ffa 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -12,7 +12,8 @@ use hir_expand::ExpansionInfo; | |||
12 | use ra_db::{FileId, FileRange}; | 12 | use ra_db::{FileId, FileRange}; |
13 | use ra_prof::profile; | 13 | use ra_prof::profile; |
14 | use ra_syntax::{ | 14 | use ra_syntax::{ |
15 | algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, | 15 | algo::{find_node_at_offset, skip_trivia_token}, |
16 | ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, | ||
16 | }; | 17 | }; |
17 | use rustc_hash::{FxHashMap, FxHashSet}; | 18 | use rustc_hash::{FxHashMap, FxHashSet}; |
18 | 19 | ||
@@ -108,6 +109,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
108 | token.value | 109 | token.value |
109 | } | 110 | } |
110 | 111 | ||
112 | pub fn descend_node_at_offset<N: ast::AstNode>( | ||
113 | &self, | ||
114 | node: &SyntaxNode, | ||
115 | offset: TextUnit, | ||
116 | ) -> Option<N> { | ||
117 | // Handle macro token cases | ||
118 | node.token_at_offset(offset) | ||
119 | .map(|token| self.descend_into_macros(token)) | ||
120 | .find_map(|it| self.ancestors_with_macros(it.parent()).find_map(N::cast)) | ||
121 | } | ||
122 | |||
111 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { | 123 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { |
112 | let node = self.find_file(node.clone()); | 124 | let node = self.find_file(node.clone()); |
113 | original_range(self.db, node.as_ref()) | 125 | original_range(self.db, node.as_ref()) |
@@ -129,6 +141,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
129 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) | 141 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) |
130 | } | 142 | } |
131 | 143 | ||
144 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*, | ||
145 | /// search up until it is of the target AstNode type | ||
132 | pub fn find_node_at_offset_with_macros<N: AstNode>( | 146 | pub fn find_node_at_offset_with_macros<N: AstNode>( |
133 | &self, | 147 | &self, |
134 | node: &SyntaxNode, | 148 | node: &SyntaxNode, |
@@ -137,6 +151,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
137 | self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) | 151 | self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) |
138 | } | 152 | } |
139 | 153 | ||
154 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*, | ||
155 | /// descend it and find again | ||
156 | pub fn find_node_at_offset_with_descend<N: AstNode>( | ||
157 | &self, | ||
158 | node: &SyntaxNode, | ||
159 | offset: TextUnit, | ||
160 | ) -> Option<N> { | ||
161 | if let Some(it) = find_node_at_offset(&node, offset) { | ||
162 | return Some(it); | ||
163 | } | ||
164 | self.descend_node_at_offset(&node, offset) | ||
165 | } | ||
166 | |||
140 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 167 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
141 | self.analyze(expr.syntax()).type_of(self.db, &expr) | 168 | self.analyze(expr.syntax()).type_of(self.db, &expr) |
142 | } | 169 | } |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index e8afef328..10c12c910 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -17,7 +17,7 @@ use hir_def::{ | |||
17 | AsMacroCall, DefWithBodyId, | 17 | AsMacroCall, DefWithBodyId, |
18 | }; | 18 | }; |
19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
20 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; | 20 | use hir_ty::InferenceResult; |
21 | use ra_syntax::{ | 21 | use ra_syntax::{ |
22 | ast::{self, AstNode}, | 22 | ast::{self, AstNode}, |
23 | SyntaxNode, SyntaxNodePtr, TextUnit, | 23 | SyntaxNode, SyntaxNodePtr, TextUnit, |
@@ -103,10 +103,6 @@ impl SourceAnalyzer { | |||
103 | Some(res) | 103 | Some(res) |
104 | } | 104 | } |
105 | 105 | ||
106 | fn trait_env(&self, db: &dyn HirDatabase) -> Arc<TraitEnvironment> { | ||
107 | TraitEnvironment::lower(db, &self.resolver) | ||
108 | } | ||
109 | |||
110 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { | 106 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { |
111 | let expr_id = match expr { | 107 | let expr_id = match expr { |
112 | ast::Expr::MacroCall(call) => { | 108 | ast::Expr::MacroCall(call) => { |
@@ -117,15 +113,13 @@ impl SourceAnalyzer { | |||
117 | }?; | 113 | }?; |
118 | 114 | ||
119 | let ty = self.infer.as_ref()?[expr_id].clone(); | 115 | let ty = self.infer.as_ref()?[expr_id].clone(); |
120 | let environment = self.trait_env(db); | 116 | Type::new_with_resolver(db, &self.resolver, ty) |
121 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
122 | } | 117 | } |
123 | 118 | ||
124 | pub(crate) fn type_of_pat(&self, db: &dyn HirDatabase, pat: &ast::Pat) -> Option<Type> { | 119 | pub(crate) fn type_of_pat(&self, db: &dyn HirDatabase, pat: &ast::Pat) -> Option<Type> { |
125 | let pat_id = self.pat_id(pat)?; | 120 | let pat_id = self.pat_id(pat)?; |
126 | let ty = self.infer.as_ref()?[pat_id].clone(); | 121 | let ty = self.infer.as_ref()?[pat_id].clone(); |
127 | let environment = self.trait_env(db); | 122 | Type::new_with_resolver(db, &self.resolver, ty) |
128 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
129 | } | 123 | } |
130 | 124 | ||
131 | pub(crate) fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 125 | pub(crate) fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |