aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/semantics.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-29 17:32:18 +0000
committerAleksey Kladov <[email protected]>2020-02-29 17:32:18 +0000
commit28332d9b63ed58ecc33604d04488f07ff75a553d (patch)
tree9d3c5dcbffffe51481b148d8cd143efc4f19ec84 /crates/ra_hir/src/semantics.rs
parenta6a623dfbb40b79cac7857165114fa11a25e4e1f (diff)
Simplify SourceBinder
Diffstat (limited to 'crates/ra_hir/src/semantics.rs')
-rw-r--r--crates/ra_hir/src/semantics.rs101
1 files changed, 40 insertions, 61 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 4a9cb7b3e..60392947e 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -1,32 +1,33 @@
1//! See `Semantics`. 1//! See `Semantics`.
2 2
3mod source_to_def;
4
3use std::{cell::RefCell, fmt, iter::successors}; 5use std::{cell::RefCell, fmt, iter::successors};
4 6
5use hir_def::{ 7use hir_def::{
6 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
7 DefWithBodyId, TraitId, 9 TraitId,
8}; 10};
11use hir_expand::ExpansionInfo;
9use ra_db::{FileId, FileRange}; 12use ra_db::{FileId, FileRange};
13use ra_prof::profile;
10use ra_syntax::{ 14use ra_syntax::{
11 algo::skip_trivia_token, ast, match_ast, AstNode, Direction, SyntaxNode, SyntaxToken, 15 algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit,
12 TextRange, TextUnit,
13}; 16};
14use rustc_hash::{FxHashMap, FxHashSet}; 17use rustc_hash::{FxHashMap, FxHashSet};
15 18
16use crate::{ 19use crate::{
17 db::HirDatabase, 20 db::HirDatabase,
21 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
18 source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, 22 source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer},
19 source_binder::{ChildContainer, SourceBinder},
20 Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, 23 Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path,
21 PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, 24 PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
22}; 25};
23use hir_expand::ExpansionInfo;
24use ra_prof::profile;
25 26
26/// Primary API to get semantic information, like types, from syntax trees. 27/// Primary API to get semantic information, like types, from syntax trees.
27pub struct Semantics<'db, DB> { 28pub struct Semantics<'db, DB> {
28 pub db: &'db DB, 29 pub db: &'db DB,
29 sb: RefCell<SourceBinder>, 30 s2d_cache: RefCell<SourceToDefCache>,
30 cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, 31 cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
31} 32}
32 33
@@ -38,8 +39,7 @@ impl<DB> fmt::Debug for Semantics<'_, DB> {
38 39
39impl<'db, DB: HirDatabase> Semantics<'db, DB> { 40impl<'db, DB: HirDatabase> Semantics<'db, DB> {
40 pub fn new(db: &DB) -> Semantics<DB> { 41 pub fn new(db: &DB) -> Semantics<DB> {
41 let sb = RefCell::new(SourceBinder::new()); 42 Semantics { db, s2d_cache: Default::default(), cache: Default::default() }
42 Semantics { db, sb, cache: RefCell::default() }
43 } 43 }
44 44
45 pub fn parse(&self, file_id: FileId) -> ast::SourceFile { 45 pub fn parse(&self, file_id: FileId) -> ast::SourceFile {
@@ -136,13 +136,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
136 // FIXME: use this instead? 136 // FIXME: use this instead?
137 // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; 137 // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
138 138
139 pub fn to_def<T: ToDef + Clone>(&self, src: &T) -> Option<T::Def> { 139 pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
140 let src = self.find_file(src.syntax().clone()).with_value(src).cloned();
140 T::to_def(self, src) 141 T::to_def(self, src)
141 } 142 }
142 143
144 fn with_ctx<F: FnOnce(&mut SourceToDefCtx<&DB>) -> T, T>(&self, f: F) -> T {
145 let mut cache = self.s2d_cache.borrow_mut();
146 let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache };
147 f(&mut ctx)
148 }
149
143 pub fn to_module_def(&self, file: FileId) -> Option<Module> { 150 pub fn to_module_def(&self, file: FileId) -> Option<Module> {
144 let mut sb = self.sb.borrow_mut(); 151 self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from)
145 sb.to_module_def(self.db, file)
146 } 152 }
147 153
148 pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db, DB> { 154 pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db, DB> {
@@ -176,7 +182,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
176 fn analyze2(&self, src: InFile<&SyntaxNode>, offset: Option<TextUnit>) -> SourceAnalyzer { 182 fn analyze2(&self, src: InFile<&SyntaxNode>, offset: Option<TextUnit>) -> SourceAnalyzer {
177 let _p = profile("Semantics::analyze2"); 183 let _p = profile("Semantics::analyze2");
178 184
179 let container = match self.sb.borrow_mut().find_container(self.db, src) { 185 let container = match self.with_ctx(|ctx| ctx.find_container(src)) {
180 Some(it) => it, 186 Some(it) => it,
181 None => return SourceAnalyzer::new_for_resolver(Resolver::default(), src), 187 None => return SourceAnalyzer::new_for_resolver(Resolver::default(), src),
182 }; 188 };
@@ -233,68 +239,41 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
233 } 239 }
234} 240}
235 241
236pub trait ToDef: Sized + AstNode + 'static { 242pub trait ToDef: AstNode + Clone {
237 type Def; 243 type Def;
238 fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) -> Option<Self::Def>; 244
245 fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def>;
239} 246}
240 247
241macro_rules! to_def_impls { 248macro_rules! to_def_impls {
242 ($(($def:path, $ast:path)),* ,) => {$( 249 ($(($def:path, $ast:path, $meth:ident)),* ,) => {$(
243 impl ToDef for $ast { 250 impl ToDef for $ast {
244 type Def = $def; 251 type Def = $def;
245 fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) 252 fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def> {
246 -> Option<Self::Def> 253 sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from)
247 {
248 let src = sema.find_file(src.syntax().clone()).with_value(src);
249 sema.sb.borrow_mut().to_id(sema.db, src.cloned()).map(Into::into)
250 } 254 }
251 } 255 }
252 )*} 256 )*}
253} 257}
254 258
255to_def_impls![ 259to_def_impls![
256 (crate::Module, ast::Module), 260 (crate::Module, ast::Module, module_to_def),
257 (crate::Struct, ast::StructDef), 261 (crate::Struct, ast::StructDef, struct_to_def),
258 (crate::Enum, ast::EnumDef), 262 (crate::Enum, ast::EnumDef, enum_to_def),
259 (crate::Union, ast::UnionDef), 263 (crate::Union, ast::UnionDef, union_to_def),
260 (crate::Trait, ast::TraitDef), 264 (crate::Trait, ast::TraitDef, trait_to_def),
261 (crate::ImplBlock, ast::ImplBlock), 265 (crate::ImplBlock, ast::ImplBlock, impl_to_def),
262 (crate::TypeAlias, ast::TypeAliasDef), 266 (crate::TypeAlias, ast::TypeAliasDef, type_alias_to_def),
263 (crate::Const, ast::ConstDef), 267 (crate::Const, ast::ConstDef, const_to_def),
264 (crate::Static, ast::StaticDef), 268 (crate::Static, ast::StaticDef, static_to_def),
265 (crate::Function, ast::FnDef), 269 (crate::Function, ast::FnDef, fn_to_def),
266 (crate::StructField, ast::RecordFieldDef), 270 (crate::StructField, ast::RecordFieldDef, record_field_to_def),
267 (crate::EnumVariant, ast::EnumVariant), 271 (crate::EnumVariant, ast::EnumVariant, enum_variant_to_def),
268 (crate::TypeParam, ast::TypeParam), 272 (crate::TypeParam, ast::TypeParam, type_param_to_def),
269 (crate::MacroDef, ast::MacroCall), // this one is dubious, not all calls are macros 273 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros
274 (crate::Local, ast::BindPat, bind_pat_to_def),
270]; 275];
271 276
272impl ToDef for ast::BindPat {
273 type Def = Local;
274
275 fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: &Self) -> Option<Local> {
276 let src = sema.find_file(src.syntax().clone()).with_value(src);
277 let file_id = src.file_id;
278 let mut sb = sema.sb.borrow_mut();
279 let db = sema.db;
280 let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| {
281 let res = match_ast! {
282 match it {
283 ast::ConstDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() },
284 ast::StaticDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() },
285 ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() },
286 _ => return None,
287 }
288 };
289 Some(res)
290 })?;
291 let (_body, source_map) = db.body_with_source_map(parent);
292 let src = src.cloned().map(ast::Pat::from);
293 let pat_id = source_map.node_pat(src.as_ref())?;
294 Some(Local { parent: parent.into(), pat_id })
295 }
296}
297
298fn find_root(node: &SyntaxNode) -> SyntaxNode { 277fn find_root(node: &SyntaxNode) -> SyntaxNode {
299 node.ancestors().last().unwrap() 278 node.ancestors().last().unwrap()
300} 279}