aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/src/lib.rs2
-rw-r--r--crates/ra_syntax/src/ptr.rs53
2 files changed, 55 insertions, 0 deletions
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}