aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_db/src/syntax_ptr.rs52
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs13
-rw-r--r--crates/ra_hir/src/expr.rs50
-rw-r--r--crates/ra_hir/src/macros.rs13
-rw-r--r--crates/ra_hir/src/nameres/lower.rs10
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
-rw-r--r--crates/ra_ide_api/src/call_info.rs4
-rw-r--r--crates/ra_ide_api/src/imp.rs2
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs14
-rw-r--r--crates/ra_syntax/src/lib.rs2
-rw-r--r--crates/ra_syntax/src/ptr.rs53
12 files changed, 109 insertions, 108 deletions
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index dbeb9ec71..32d7e09b9 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -1,6 +1,5 @@
1//! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api. 1//! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api.
2mod cancellation; 2mod cancellation;
3mod syntax_ptr;
4mod input; 3mod input;
5mod loc2id; 4mod loc2id;
6pub mod mock; 5pub mod mock;
@@ -12,7 +11,6 @@ use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc};
12pub use ::salsa as salsa; 11pub use ::salsa as salsa;
13pub use crate::{ 12pub use crate::{
14 cancellation::Canceled, 13 cancellation::Canceled,
15 syntax_ptr::LocalSyntaxPtr,
16 input::{ 14 input::{
17 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, 15 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency,
18 FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, 16 FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery,
diff --git a/crates/ra_db/src/syntax_ptr.rs b/crates/ra_db/src/syntax_ptr.rs
deleted file mode 100644
index 5270826da..000000000
--- a/crates/ra_db/src/syntax_ptr.rs
+++ /dev/null
@@ -1,52 +0,0 @@
1use ra_syntax::{AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, TreeArc};
2
3/// A pointer to a syntax node inside a file.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct LocalSyntaxPtr {
6 range: TextRange,
7 kind: SyntaxKind,
8}
9
10impl LocalSyntaxPtr {
11 pub fn new(node: &SyntaxNode) -> LocalSyntaxPtr {
12 LocalSyntaxPtr {
13 range: node.range(),
14 kind: node.kind(),
15 }
16 }
17
18 pub fn resolve(self, file: &SourceFile) -> TreeArc<SyntaxNode> {
19 let mut curr = file.syntax();
20 loop {
21 if curr.range() == self.range && curr.kind() == self.kind {
22 return curr.to_owned();
23 }
24 curr = curr
25 .children()
26 .find(|it| self.range.is_subrange(&it.range()))
27 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
28 }
29 }
30
31 pub fn range(self) -> TextRange {
32 self.range
33 }
34
35 pub fn kind(self) -> SyntaxKind {
36 self.kind
37 }
38}
39
40#[test]
41fn test_local_syntax_ptr() {
42 use ra_syntax::{ast, AstNode};
43 let file = SourceFile::parse("struct Foo { f: u32, }");
44 let field = file
45 .syntax()
46 .descendants()
47 .find_map(ast::NamedFieldDef::cast)
48 .unwrap();
49 let ptr = LocalSyntaxPtr::new(field.syntax());
50 let field_syntax = ptr.resolve(&file);
51 assert_eq!(field.syntax(), &*field_syntax);
52}
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs
index 3a7d53a93..c5d1de5eb 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/code_model_impl/function/scope.rs
@@ -3,12 +3,11 @@ use std::sync::Arc;
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4 4
5use ra_syntax::{ 5use ra_syntax::{
6 AstNode, SyntaxNode, TextUnit, TextRange, 6 AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr,
7 algo::generate, 7 algo::generate,
8 ast, 8 ast,
9}; 9};
10use ra_arena::{Arena, RawId, impl_arena_id}; 10use ra_arena::{Arena, RawId, impl_arena_id};
11use ra_db::LocalSyntaxPtr;
12 11
13use crate::{Name, AsName, expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}}; 12use crate::{Name, AsName, expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}};
14 13
@@ -126,7 +125,7 @@ pub struct ScopesWithSyntaxMapping {
126#[derive(Debug, Clone, PartialEq, Eq)] 125#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct ScopeEntryWithSyntax { 126pub struct ScopeEntryWithSyntax {
128 name: Name, 127 name: Name,
129 ptr: LocalSyntaxPtr, 128 ptr: SyntaxNodePtr,
130} 129}
131 130
132impl ScopeEntryWithSyntax { 131impl ScopeEntryWithSyntax {
@@ -134,7 +133,7 @@ impl ScopeEntryWithSyntax {
134 &self.name 133 &self.name
135 } 134 }
136 135
137 pub fn ptr(&self) -> LocalSyntaxPtr { 136 pub fn ptr(&self) -> SyntaxNodePtr {
138 self.ptr 137 self.ptr
139 } 138 }
140} 139}
@@ -169,7 +168,7 @@ impl ScopesWithSyntaxMapping {
169 168
170 // XXX: during completion, cursor might be outside of any particular 169 // XXX: during completion, cursor might be outside of any particular
171 // expression. Try to figure out the correct scope... 170 // expression. Try to figure out the correct scope...
172 fn adjust(&self, ptr: LocalSyntaxPtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { 171 fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId {
173 let r = ptr.range(); 172 let r = ptr.range();
174 let child_scopes = self 173 let child_scopes = self
175 .scopes 174 .scopes
@@ -212,7 +211,7 @@ impl ScopesWithSyntaxMapping {
212 211
213 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { 212 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
214 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); 213 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
215 let name_ptr = LocalSyntaxPtr::new(pat.syntax()); 214 let name_ptr = SyntaxNodePtr::new(pat.syntax());
216 fn_def 215 fn_def
217 .syntax() 216 .syntax()
218 .descendants() 217 .descendants()
@@ -230,7 +229,7 @@ impl ScopesWithSyntaxMapping {
230 229
231 fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> { 230 fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> {
232 node.ancestors() 231 node.ancestors()
233 .map(LocalSyntaxPtr::new) 232 .map(SyntaxNodePtr::new)
234 .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr)) 233 .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr))
235 .find_map(|it| self.scopes.scope_for(it)) 234 .find_map(|it| self.scopes.scope_for(it))
236 } 235 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 51dae8e25..1a3821692 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -4,8 +4,10 @@ use std::sync::Arc;
4use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
5 5
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_db::LocalSyntaxPtr; 7use ra_syntax::{
8use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor}; 8 SyntaxNodePtr, AstNode,
9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor}
10};
9 11
10use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; 12use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName};
11use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; 13use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
@@ -38,10 +40,10 @@ pub struct Body {
38#[derive(Debug, Eq, PartialEq)] 40#[derive(Debug, Eq, PartialEq)]
39pub struct BodySyntaxMapping { 41pub struct BodySyntaxMapping {
40 body: Arc<Body>, 42 body: Arc<Body>,
41 expr_syntax_mapping: FxHashMap<LocalSyntaxPtr, ExprId>, 43 expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>,
42 expr_syntax_mapping_back: ArenaMap<ExprId, LocalSyntaxPtr>, 44 expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>,
43 pat_syntax_mapping: FxHashMap<LocalSyntaxPtr, PatId>, 45 pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>,
44 pat_syntax_mapping_back: ArenaMap<PatId, LocalSyntaxPtr>, 46 pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>,
45} 47}
46 48
47impl Body { 49impl Body {
@@ -71,31 +73,31 @@ impl Index<PatId> for Body {
71} 73}
72 74
73impl BodySyntaxMapping { 75impl BodySyntaxMapping {
74 pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> { 76 pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> {
75 self.expr_syntax_mapping_back.get(expr).cloned() 77 self.expr_syntax_mapping_back.get(expr).cloned()
76 } 78 }
77 79
78 pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> { 80 pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
79 self.expr_syntax_mapping.get(&ptr).cloned() 81 self.expr_syntax_mapping.get(&ptr).cloned()
80 } 82 }
81 83
82 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 84 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
83 self.expr_syntax_mapping 85 self.expr_syntax_mapping
84 .get(&LocalSyntaxPtr::new(node.syntax())) 86 .get(&SyntaxNodePtr::new(node.syntax()))
85 .cloned() 87 .cloned()
86 } 88 }
87 89
88 pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> { 90 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> {
89 self.pat_syntax_mapping_back.get(pat).cloned() 91 self.pat_syntax_mapping_back.get(pat).cloned()
90 } 92 }
91 93
92 pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> { 94 pub fn syntax_pat(&self, ptr: SyntaxNodePtr) -> Option<PatId> {
93 self.pat_syntax_mapping.get(&ptr).cloned() 95 self.pat_syntax_mapping.get(&ptr).cloned()
94 } 96 }
95 97
96 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 98 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
97 self.pat_syntax_mapping 99 self.pat_syntax_mapping
98 .get(&LocalSyntaxPtr::new(node.syntax())) 100 .get(&SyntaxNodePtr::new(node.syntax()))
99 .cloned() 101 .cloned()
100 } 102 }
101 103
@@ -440,10 +442,10 @@ pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc<Body> {
440struct ExprCollector { 442struct ExprCollector {
441 exprs: Arena<ExprId, Expr>, 443 exprs: Arena<ExprId, Expr>,
442 pats: Arena<PatId, Pat>, 444 pats: Arena<PatId, Pat>,
443 expr_syntax_mapping: FxHashMap<LocalSyntaxPtr, ExprId>, 445 expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>,
444 expr_syntax_mapping_back: ArenaMap<ExprId, LocalSyntaxPtr>, 446 expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>,
445 pat_syntax_mapping: FxHashMap<LocalSyntaxPtr, PatId>, 447 pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>,
446 pat_syntax_mapping_back: ArenaMap<PatId, LocalSyntaxPtr>, 448 pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>,
447} 449}
448 450
449impl ExprCollector { 451impl ExprCollector {
@@ -458,14 +460,14 @@ impl ExprCollector {
458 } 460 }
459 } 461 }
460 462
461 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: LocalSyntaxPtr) -> ExprId { 463 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
462 let id = self.exprs.alloc(expr); 464 let id = self.exprs.alloc(expr);
463 self.expr_syntax_mapping.insert(syntax_ptr, id); 465 self.expr_syntax_mapping.insert(syntax_ptr, id);
464 self.expr_syntax_mapping_back.insert(id, syntax_ptr); 466 self.expr_syntax_mapping_back.insert(id, syntax_ptr);
465 id 467 id
466 } 468 }
467 469
468 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: LocalSyntaxPtr) -> PatId { 470 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: SyntaxNodePtr) -> PatId {
469 let id = self.pats.alloc(pat); 471 let id = self.pats.alloc(pat);
470 self.pat_syntax_mapping.insert(syntax_ptr, id); 472 self.pat_syntax_mapping.insert(syntax_ptr, id);
471 self.pat_syntax_mapping_back.insert(id, syntax_ptr); 473 self.pat_syntax_mapping_back.insert(id, syntax_ptr);
@@ -481,7 +483,7 @@ impl ExprCollector {
481 } 483 }
482 484
483 fn collect_expr(&mut self, expr: &ast::Expr) -> ExprId { 485 fn collect_expr(&mut self, expr: &ast::Expr) -> ExprId {
484 let syntax_ptr = LocalSyntaxPtr::new(expr.syntax()); 486 let syntax_ptr = SyntaxNodePtr::new(expr.syntax());
485 match expr.kind() { 487 match expr.kind() {
486 ast::ExprKind::IfExpr(e) => { 488 ast::ExprKind::IfExpr(e) => {
487 if let Some(pat) = e.condition().and_then(|c| c.pat()) { 489 if let Some(pat) = e.condition().and_then(|c| c.pat()) {
@@ -643,9 +645,9 @@ impl ExprCollector {
643 // field shorthand 645 // field shorthand
644 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(nr))); 646 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(nr)));
645 self.expr_syntax_mapping 647 self.expr_syntax_mapping
646 .insert(LocalSyntaxPtr::new(nr.syntax()), id); 648 .insert(SyntaxNodePtr::new(nr.syntax()), id);
647 self.expr_syntax_mapping_back 649 self.expr_syntax_mapping_back
648 .insert(id, LocalSyntaxPtr::new(nr.syntax())); 650 .insert(id, SyntaxNodePtr::new(nr.syntax()));
649 id 651 id
650 } else { 652 } else {
651 self.exprs.alloc(Expr::Missing) 653 self.exprs.alloc(Expr::Missing)
@@ -806,7 +808,7 @@ impl ExprCollector {
806 let tail = block.expr().map(|e| self.collect_expr(e)); 808 let tail = block.expr().map(|e| self.collect_expr(e));
807 self.alloc_expr( 809 self.alloc_expr(
808 Expr::Block { statements, tail }, 810 Expr::Block { statements, tail },
809 LocalSyntaxPtr::new(block.syntax()), 811 SyntaxNodePtr::new(block.syntax()),
810 ) 812 )
811 } 813 }
812 814
@@ -883,7 +885,7 @@ impl ExprCollector {
883 // TODO: implement 885 // TODO: implement
884 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing, 886 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
885 }; 887 };
886 let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); 888 let syntax_ptr = SyntaxNodePtr::new(pat.syntax());
887 self.alloc_pat(pattern, syntax_ptr) 889 self.alloc_pat(pattern, syntax_ptr)
888 } 890 }
889 891
@@ -919,7 +921,7 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
919 let mut params = Vec::new(); 921 let mut params = Vec::new();
920 922
921 if let Some(self_param) = param_list.self_param() { 923 if let Some(self_param) = param_list.self_param() {
922 let self_param = LocalSyntaxPtr::new( 924 let self_param = SyntaxNodePtr::new(
923 self_param 925 self_param
924 .self_kw() 926 .self_kw()
925 .expect("self param without self keyword") 927 .expect("self param without self keyword")
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index 220bee94e..7ca34d434 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -9,9 +9,8 @@
9/// those yet, so all macros are string based at the moment! 9/// those yet, so all macros are string based at the moment!
10use std::sync::Arc; 10use std::sync::Arc;
11 11
12use ra_db::LocalSyntaxPtr;
13use ra_syntax::{ 12use ra_syntax::{
14 TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, 13 TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, SyntaxNodePtr,
15 ast::{self, NameOwner}, 14 ast::{self, NameOwner},
16}; 15};
17 16
@@ -80,7 +79,7 @@ impl MacroDef {
80 let file = SourceFile::parse(&text); 79 let file = SourceFile::parse(&text);
81 let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; 80 let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?;
82 let match_arg = match_expr.expr()?; 81 let match_arg = match_expr.expr()?;
83 let ptr = LocalSyntaxPtr::new(match_arg.syntax()); 82 let ptr = SyntaxNodePtr::new(match_arg.syntax());
84 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); 83 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
85 let ranges_map = vec![(src_range, match_arg.syntax().range())]; 84 let ranges_map = vec![(src_range, match_arg.syntax().range())];
86 let res = MacroExpansion { 85 let res = MacroExpansion {
@@ -94,7 +93,7 @@ impl MacroDef {
94 let text = format!(r"fn dummy() {{ {}; }}", input.text); 93 let text = format!(r"fn dummy() {{ {}; }}", input.text);
95 let file = SourceFile::parse(&text); 94 let file = SourceFile::parse(&text);
96 let array_expr = file.syntax().descendants().find_map(ast::ArrayExpr::cast)?; 95 let array_expr = file.syntax().descendants().find_map(ast::ArrayExpr::cast)?;
97 let ptr = LocalSyntaxPtr::new(array_expr.syntax()); 96 let ptr = SyntaxNodePtr::new(array_expr.syntax());
98 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); 97 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
99 let ranges_map = vec![(src_range, array_expr.syntax().range())]; 98 let ranges_map = vec![(src_range, array_expr.syntax().range())];
100 let res = MacroExpansion { 99 let res = MacroExpansion {
@@ -119,7 +118,7 @@ impl MacroDef {
119 let file = SourceFile::parse(&text); 118 let file = SourceFile::parse(&text);
120 let trait_def = file.syntax().descendants().find_map(ast::TraitDef::cast)?; 119 let trait_def = file.syntax().descendants().find_map(ast::TraitDef::cast)?;
121 let name = trait_def.name()?; 120 let name = trait_def.name()?;
122 let ptr = LocalSyntaxPtr::new(trait_def.syntax()); 121 let ptr = SyntaxNodePtr::new(trait_def.syntax());
123 let ranges_map = vec![(src_range, name.syntax().range())]; 122 let ranges_map = vec![(src_range, name.syntax().range())];
124 let res = MacroExpansion { 123 let res = MacroExpansion {
125 text, 124 text,
@@ -146,7 +145,7 @@ pub struct MacroExpansion {
146 /// Implementation detail: internally, a macro is expanded to the whole file, 145 /// Implementation detail: internally, a macro is expanded to the whole file,
147 /// even if it is an expression. This `ptr` selects the actual expansion from 146 /// even if it is an expression. This `ptr` selects the actual expansion from
148 /// the expanded file. 147 /// the expanded file.
149 ptr: LocalSyntaxPtr, 148 ptr: SyntaxNodePtr,
150} 149}
151 150
152impl MacroExpansion { 151impl MacroExpansion {
@@ -157,7 +156,7 @@ impl MacroExpansion {
157 } 156 }
158 157
159 pub fn syntax(&self) -> TreeArc<SyntaxNode> { 158 pub fn syntax(&self) -> TreeArc<SyntaxNode> {
160 self.ptr.resolve(&self.file()) 159 self.ptr.to_node(&self.file()).to_owned()
161 } 160 }
162 /// Maps range in the source code to the range in the expanded code. 161 /// Maps range in the source code to the range in the expanded code.
163 pub fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> { 162 pub fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> {
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 52448644c..ab6f3a9bc 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -1,10 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 SyntaxKind, AstNode, SourceFile, TreeArc, 4 SyntaxKind, AstNode, SourceFile, TreeArc, SyntaxNodePtr,
5 ast::{self, ModuleItemOwner}, 5 ast::{self, ModuleItemOwner},
6}; 6};
7use ra_db::{SourceRootId, LocalSyntaxPtr}; 7use ra_db::{SourceRootId};
8use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 8use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
9 9
10use crate::{ 10use crate::{
@@ -72,13 +72,13 @@ pub struct LoweredModule {
72 72
73#[derive(Debug, Default, PartialEq, Eq)] 73#[derive(Debug, Default, PartialEq, Eq)]
74pub struct ImportSourceMap { 74pub struct ImportSourceMap {
75 map: ArenaMap<ImportId, LocalSyntaxPtr>, 75 map: ArenaMap<ImportId, SyntaxNodePtr>,
76} 76}
77 77
78impl ImportSourceMap { 78impl ImportSourceMap {
79 fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { 79 fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
80 self.map 80 self.map
81 .insert(import, LocalSyntaxPtr::new(segment.syntax())) 81 .insert(import, SyntaxNodePtr::new(segment.syntax()))
82 } 82 }
83 83
84 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { 84 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> {
@@ -87,7 +87,7 @@ impl ImportSourceMap {
87 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), 87 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
88 }; 88 };
89 89
90 ast::PathSegment::cast(&self.map[import].resolve(file)) 90 ast::PathSegment::cast(self.map[import].to_node(file))
91 .unwrap() 91 .unwrap()
92 .to_owned() 92 .to_owned()
93 } 93 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 9bf1fd3b2..92c74cf00 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -562,7 +562,7 @@ fn infer(content: &str) -> String {
562 // sort ranges for consistency 562 // sort ranges for consistency
563 types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end())); 563 types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end()));
564 for (syntax_ptr, ty) in &types { 564 for (syntax_ptr, ty) in &types {
565 let node = syntax_ptr.resolve(&source_file); 565 let node = syntax_ptr.to_node(&source_file);
566 write!( 566 write!(
567 acc, 567 acc,
568 "{} '{}': {}\n", 568 "{} '{}': {}\n",
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 798fb7c13..0449c1902 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -23,8 +23,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
23 .into_iter() 23 .into_iter()
24 .find(|it| it.ptr.kind() == FN_DEF)?; 24 .find(|it| it.ptr.kind() == FN_DEF)?;
25 let fn_file = db.source_file(symbol.file_id); 25 let fn_file = db.source_file(symbol.file_id);
26 let fn_def = symbol.ptr.resolve(&fn_file); 26 let fn_def = symbol.ptr.to_node(&fn_file);
27 let fn_def = ast::FnDef::cast(&fn_def).unwrap(); 27 let fn_def = ast::FnDef::cast(fn_def).unwrap();
28 let mut call_info = CallInfo::new(fn_def)?; 28 let mut call_info = CallInfo::new(fn_def)?;
29 // If we have a calling expression let's find which argument we are on 29 // If we have a calling expression let's find which argument we are on
30 let num_params = call_info.parameters.len(); 30 let num_params = call_info.parameters.len();
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs
index fa79908a1..ddd9354ec 100644
--- a/crates/ra_ide_api/src/imp.rs
+++ b/crates/ra_ide_api/src/imp.rs
@@ -153,7 +153,7 @@ impl db::RootDatabase {
153 source_binder::function_from_child_node(db, position.file_id, name_ref.syntax())?; 153 source_binder::function_from_child_node(db, position.file_id, name_ref.syntax())?;
154 let scope = descr.scopes(db); 154 let scope = descr.scopes(db);
155 let resolved = scope.resolve_local_name(name_ref)?; 155 let resolved = scope.resolve_local_name(name_ref)?;
156 let resolved = resolved.ptr().resolve(source_file); 156 let resolved = resolved.ptr().to_node(source_file);
157 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?; 157 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?;
158 Some((binding, descr)) 158 Some((binding, descr))
159 } 159 }
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index b563dfe88..1b5d1eb1d 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -27,13 +27,13 @@ use std::{
27 27
28use fst::{self, Streamer}; 28use fst::{self, Streamer};
29use ra_syntax::{ 29use ra_syntax::{
30 SyntaxNode, SourceFile, SmolStr, TreeArc, AstNode, 30 SyntaxNode, SyntaxNodePtr, SourceFile, SmolStr, TreeArc, AstNode,
31 algo::{visit::{visitor, Visitor}, find_covering_node}, 31 algo::{visit::{visitor, Visitor}, find_covering_node},
32 SyntaxKind::{self, *}, 32 SyntaxKind::{self, *},
33 ast::{self, NameOwner}, 33 ast::{self, NameOwner},
34}; 34};
35use ra_db::{ 35use ra_db::{
36 SourceRootId, FilesDatabase, LocalSyntaxPtr, 36 SourceRootId, FilesDatabase,
37 salsa::{self, ParallelDatabase}, 37 salsa::{self, ParallelDatabase},
38}; 38};
39use rayon::prelude::*; 39use rayon::prelude::*;
@@ -62,7 +62,7 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex>
62 62
63 for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) { 63 for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) {
64 let node = find_covering_node(source_file.syntax(), text_range); 64 let node = find_covering_node(source_file.syntax(), text_range);
65 let ptr = LocalSyntaxPtr::new(node); 65 let ptr = SyntaxNodePtr::new(node);
66 symbols.push(FileSymbol { file_id, name, ptr }) 66 symbols.push(FileSymbol { file_id, name, ptr })
67 } 67 }
68 68
@@ -196,13 +196,13 @@ fn is_type(kind: SyntaxKind) -> bool {
196pub(crate) struct FileSymbol { 196pub(crate) struct FileSymbol {
197 pub(crate) file_id: FileId, 197 pub(crate) file_id: FileId,
198 pub(crate) name: SmolStr, 198 pub(crate) name: SmolStr,
199 pub(crate) ptr: LocalSyntaxPtr, 199 pub(crate) ptr: SyntaxNodePtr,
200} 200}
201 201
202fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, LocalSyntaxPtr)> { 202fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> {
203 fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, LocalSyntaxPtr)> { 203 fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> {
204 let name = node.name()?.text().clone(); 204 let name = node.name()?.text().clone();
205 let ptr = LocalSyntaxPtr::new(node.syntax()); 205 let ptr = SyntaxNodePtr::new(node.syntax());
206 Some((name, ptr)) 206 Some((name, ptr))
207 } 207 }
208 visitor() 208 visitor()
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index bc311cbbc..97b196118 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -35,6 +35,7 @@ mod syntax_kinds;
35pub mod utils; 35pub mod utils;
36mod validation; 36mod validation;
37mod yellow; 37mod yellow;
38mod ptr;
38 39
39pub use rowan::{SmolStr, TextRange, TextUnit}; 40pub use rowan::{SmolStr, TextRange, TextUnit};
40pub use crate::{ 41pub use crate::{
@@ -42,6 +43,7 @@ pub use crate::{
42 lexer::{tokenize, Token}, 43 lexer::{tokenize, Token},
43 syntax_kinds::SyntaxKind, 44 syntax_kinds::SyntaxKind,
44 yellow::{Direction, SyntaxError, SyntaxNode, WalkEvent, Location, TreeArc}, 45 yellow::{Direction, SyntaxError, SyntaxNode, WalkEvent, Location, TreeArc},
46 ptr::SyntaxNodePtr,
45}; 47};
46 48
47use ra_text_edit::AtomTextEdit; 49use ra_text_edit::AtomTextEdit;
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
new file mode 100644
index 000000000..e8c40e5d3
--- /dev/null
+++ b/crates/ra_syntax/src/ptr.rs
@@ -0,0 +1,53 @@
1use crate::{
2 AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange,
3 algo::generate,
4};
5
6/// A pointer to a syntax node inside a file. It can be used to remember a
7/// specific node across reparses of the same file.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct SyntaxNodePtr {
10 range: TextRange,
11 kind: SyntaxKind,
12}
13
14impl SyntaxNodePtr {
15 pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
16 SyntaxNodePtr {
17 range: node.range(),
18 kind: node.kind(),
19 }
20 }
21
22 pub fn to_node(self, source_file: &SourceFile) -> &SyntaxNode {
23 generate(Some(source_file.syntax()), |&node| {
24 node.children()
25 .find(|it| self.range.is_subrange(&it.range()))
26 })
27 .find(|it| it.range() == self.range && it.kind() == self.kind)
28 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
29 }
30
31 pub fn range(self) -> TextRange {
32 self.range
33 }
34
35 pub fn kind(self) -> SyntaxKind {
36 self.kind
37 }
38}
39
40#[test]
41fn test_local_syntax_ptr() {
42 use crate::{ast, AstNode};
43
44 let file = SourceFile::parse("struct Foo { f: u32, }");
45 let field = file
46 .syntax()
47 .descendants()
48 .find_map(ast::NamedFieldDef::cast)
49 .unwrap();
50 let ptr = SyntaxNodePtr::new(field.syntax());
51 let field_syntax = ptr.to_node(&file);
52 assert_eq!(field.syntax(), &*field_syntax);
53}