aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model.rs66
-rw-r--r--crates/ra_hir/src/from_id.rs21
-rw-r--r--crates/ra_hir/src/lib.rs12
-rw-r--r--crates/ra_hir/src/semantics.rs29
-rw-r--r--crates/ra_hir/src/source_analyzer.rs12
6 files changed, 91 insertions, 51 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 42193b492..ba7b39a19 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -13,7 +13,7 @@ rustc-hash = "1.1.0"
13either = "1.5.3" 13either = "1.5.3"
14arrayvec = "0.5.1" 14arrayvec = "0.5.1"
15 15
16itertools = "0.8.2" 16itertools = "0.9.0"
17 17
18ra_syntax = { path = "../ra_syntax" } 18ra_syntax = { path = "../ra_syntax" }
19ra_db = { path = "../ra_db" } 19ra_db = { path = "../ra_db" }
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};
34use rustc_hash::FxHashSet; 34use rustc_hash::FxHashSet;
35 35
36use crate::{db::HirDatabase, has_source::HasSource, CallableDef, HirDisplay, InFile, Name}; 36use 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
285fn 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)]
1022pub struct Type { 1014pub struct Type {
1023 pub(crate) krate: CrateId, 1015 krate: CrateId,
1024 pub(crate) ty: InEnvironment<Ty>, 1016 ty: InEnvironment<Ty>,
1025} 1017}
1026 1018
1027impl Type { 1019impl 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
11use crate::{ 11use 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
16macro_rules! from_id { 16macro_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
232impl From<MacroDef> for ItemInNs {
233 fn from(macro_def: MacroDef) -> Self {
234 ItemInNs::Macros(macro_def.into())
235 }
236}
237
238impl 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;
12use ra_db::{FileId, FileRange}; 12use ra_db::{FileId, FileRange};
13use ra_prof::profile; 13use ra_prof::profile;
14use ra_syntax::{ 14use 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};
17use rustc_hash::{FxHashMap, FxHashSet}; 18use 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};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; 20use hir_ty::InferenceResult;
21use ra_syntax::{ 21use 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> {