aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r--crates/ra_analysis/src/lib.rs1
-rw-r--r--crates/ra_analysis/src/syntax_ptr.rs67
2 files changed, 68 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index a67cac21e..363c72c0b 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -12,6 +12,7 @@ mod descriptors;
12mod imp; 12mod imp;
13mod symbol_index; 13mod symbol_index;
14mod completion; 14mod completion;
15mod syntax_ptr;
15 16
16use std::{ 17use std::{
17 fmt, 18 fmt,
diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_analysis/src/syntax_ptr.rs
new file mode 100644
index 000000000..863ad2672
--- /dev/null
+++ b/crates/ra_analysis/src/syntax_ptr.rs
@@ -0,0 +1,67 @@
1use ra_syntax::{
2 File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef,
3 ast::{self, AstNode},
4};
5
6use crate::FileId;
7use crate::db::SyntaxDatabase;
8
9/// SyntaxPtr is a cheap `Copy` id which identifies a particular syntax node,
10/// without retainig syntax tree in memory. You need to explicitelly `resovle`
11/// `SyntaxPtr` to get a `SyntaxNode`
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub(crate) struct SyntaxPtr {
14 file_id: FileId,
15 local: LocalSyntaxPtr,
16}
17
18impl SyntaxPtr {
19 pub(crate) fn new(file_id: FileId, node: SyntaxNodeRef) -> SyntaxPtr {
20 let local = LocalSyntaxPtr::new(node);
21 SyntaxPtr { file_id, local }
22 }
23
24 pub(crate) fn resolve(self, db: &impl SyntaxDatabase) -> SyntaxNode {
25 let syntax = db.file_syntax(self.file_id);
26 self.local.resolve(&syntax)
27 }
28}
29
30
31/// A pionter to a syntax node inside a file.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33struct LocalSyntaxPtr {
34 range: TextRange,
35 kind: SyntaxKind,
36}
37
38impl LocalSyntaxPtr {
39 fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
40 LocalSyntaxPtr {
41 range: node.range(),
42 kind: node.kind(),
43 }
44 }
45
46 fn resolve(self, file: &File) -> SyntaxNode {
47 let mut curr = file.syntax();
48 loop {
49 if curr.range() == self.range && curr.kind() == self.kind {
50 return curr.owned();
51 }
52 curr = curr.children()
53 .find(|it| self.range.is_subrange(&it.range()))
54 .unwrap_or_else(|| panic!("can't resovle local ptr to SyntaxNode: {:?}", self))
55 }
56 }
57}
58
59
60#[test]
61fn test_local_syntax_ptr() {
62 let file = File::parse("struct Foo { f: u32, }");
63 let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap();
64 let ptr = LocalSyntaxPtr::new(field.syntax());
65 let field_syntax = ptr.resolve(&file);
66 assert_eq!(field.syntax(), field_syntax);
67}