From 7b901f86cd1d0198994e5a2ab7eea18f444dd148 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 23 Jan 2019 17:37:10 +0300 Subject: move SyntaxPtr to ra_syntax --- crates/ra_syntax/src/lib.rs | 2 ++ crates/ra_syntax/src/ptr.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 crates/ra_syntax/src/ptr.rs (limited to 'crates/ra_syntax') 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; pub mod utils; mod validation; mod yellow; +mod ptr; pub use rowan::{SmolStr, TextRange, TextUnit}; pub use crate::{ @@ -42,6 +43,7 @@ pub use crate::{ lexer::{tokenize, Token}, syntax_kinds::SyntaxKind, yellow::{Direction, SyntaxError, SyntaxNode, WalkEvent, Location, TreeArc}, + ptr::SyntaxNodePtr, }; use 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 @@ +use crate::{ + AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, + algo::generate, +}; + +/// A pointer to a syntax node inside a file. It can be used to remember a +/// specific node across reparses of the same file. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct SyntaxNodePtr { + range: TextRange, + kind: SyntaxKind, +} + +impl SyntaxNodePtr { + pub fn new(node: &SyntaxNode) -> SyntaxNodePtr { + SyntaxNodePtr { + range: node.range(), + kind: node.kind(), + } + } + + pub fn to_node(self, source_file: &SourceFile) -> &SyntaxNode { + generate(Some(source_file.syntax()), |&node| { + node.children() + .find(|it| self.range.is_subrange(&it.range())) + }) + .find(|it| it.range() == self.range && it.kind() == self.kind) + .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) + } + + pub fn range(self) -> TextRange { + self.range + } + + pub fn kind(self) -> SyntaxKind { + self.kind + } +} + +#[test] +fn test_local_syntax_ptr() { + use crate::{ast, AstNode}; + + let file = SourceFile::parse("struct Foo { f: u32, }"); + let field = file + .syntax() + .descendants() + .find_map(ast::NamedFieldDef::cast) + .unwrap(); + let ptr = SyntaxNodePtr::new(field.syntax()); + let field_syntax = ptr.to_node(&file); + assert_eq!(field.syntax(), &*field_syntax); +} -- cgit v1.2.3