diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 20 | ||||
-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 |
4 files changed, 57 insertions, 16 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 4b150ef06..e91abf6f5 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, |
@@ -912,10 +912,8 @@ impl Local { | |||
912 | let def = DefWithBodyId::from(self.parent); | 912 | let def = DefWithBodyId::from(self.parent); |
913 | let infer = db.infer(def); | 913 | let infer = db.infer(def); |
914 | let ty = infer[self.pat_id].clone(); | 914 | let ty = infer[self.pat_id].clone(); |
915 | let resolver = def.resolver(db.upcast()); | ||
916 | let krate = def.module(db.upcast()).krate; | 915 | let krate = def.module(db.upcast()).krate; |
917 | let environment = TraitEnvironment::lower(db, &resolver); | 916 | Type::new(db, krate, def, ty) |
918 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
919 | } | 917 | } |
920 | 918 | ||
921 | pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::BindPat, ast::SelfParam>> { | 919 | pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::BindPat, ast::SelfParam>> { |
@@ -1020,11 +1018,21 @@ impl ImplDef { | |||
1020 | 1018 | ||
1021 | #[derive(Clone, PartialEq, Eq, Debug)] | 1019 | #[derive(Clone, PartialEq, Eq, Debug)] |
1022 | pub struct Type { | 1020 | pub struct Type { |
1023 | pub(crate) krate: CrateId, | 1021 | krate: CrateId, |
1024 | pub(crate) ty: InEnvironment<Ty>, | 1022 | ty: InEnvironment<Ty>, |
1025 | } | 1023 | } |
1026 | 1024 | ||
1027 | impl Type { | 1025 | impl Type { |
1026 | pub(crate) fn new_with_resolver( | ||
1027 | db: &dyn HirDatabase, | ||
1028 | resolver: &Resolver, | ||
1029 | ty: Ty, | ||
1030 | ) -> Option<Type> { | ||
1031 | let krate = resolver.krate()?; | ||
1032 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1033 | Some(Type { krate, ty: InEnvironment { value: ty, environment } }) | ||
1034 | } | ||
1035 | |||
1028 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { | 1036 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { |
1029 | let resolver = lexical_env.resolver(db.upcast()); | 1037 | let resolver = lexical_env.resolver(db.upcast()); |
1030 | let environment = TraitEnvironment::lower(db, &resolver); | 1038 | let environment = TraitEnvironment::lower(db, &resolver); |
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> { |