From 950e8b8182897da60bcece70d84e9f0b6dc88632 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Oct 2018 21:23:23 +0300 Subject: introduce syntax-ptr --- Cargo.lock | 11 +++--- crates/ra_analysis/src/lib.rs | 1 + crates/ra_analysis/src/syntax_ptr.rs | 67 ++++++++++++++++++++++++++++++++++++ crates/ra_syntax/Cargo.toml | 1 + 4 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 crates/ra_analysis/src/syntax_ptr.rs diff --git a/Cargo.lock b/Cargo.lock index 16eaf3738..88c7ba356 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -661,7 +661,7 @@ dependencies = [ "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -675,6 +675,7 @@ dependencies = [ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rowan 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", + "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -798,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1038,12 +1039,12 @@ version = "0.1.0" dependencies = [ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "text_unit" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1372,7 +1373,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tera 0.11.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6c87cae42cc4fc480278c7583792cc5da2d51a25be916b7921cbb45c43063b8d" "checksum teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d89ad4617d1dec55331067fadaa041e813479e1779616f3d3ce9308bf46184e" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc86da66d0b9aa8d359b0ec31b4342c6bc52637eadef05b91b098551a9f8e9" +"checksum text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8009d7bdbd896a7e09b595f8f9325a19047fc708653e60d0895202b82135048f" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" 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; mod imp; mod symbol_index; mod completion; +mod syntax_ptr; use std::{ 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 @@ +use ra_syntax::{ + File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef, + ast::{self, AstNode}, +}; + +use crate::FileId; +use crate::db::SyntaxDatabase; + +/// SyntaxPtr is a cheap `Copy` id which identifies a particular syntax node, +/// without retainig syntax tree in memory. You need to explicitelly `resovle` +/// `SyntaxPtr` to get a `SyntaxNode` +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct SyntaxPtr { + file_id: FileId, + local: LocalSyntaxPtr, +} + +impl SyntaxPtr { + pub(crate) fn new(file_id: FileId, node: SyntaxNodeRef) -> SyntaxPtr { + let local = LocalSyntaxPtr::new(node); + SyntaxPtr { file_id, local } + } + + pub(crate) fn resolve(self, db: &impl SyntaxDatabase) -> SyntaxNode { + let syntax = db.file_syntax(self.file_id); + self.local.resolve(&syntax) + } +} + + +/// A pionter to a syntax node inside a file. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct LocalSyntaxPtr { + range: TextRange, + kind: SyntaxKind, +} + +impl LocalSyntaxPtr { + fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr { + LocalSyntaxPtr { + range: node.range(), + kind: node.kind(), + } + } + + fn resolve(self, file: &File) -> SyntaxNode { + let mut curr = file.syntax(); + loop { + if curr.range() == self.range && curr.kind() == self.kind { + return curr.owned(); + } + curr = curr.children() + .find(|it| self.range.is_subrange(&it.range())) + .unwrap_or_else(|| panic!("can't resovle local ptr to SyntaxNode: {:?}", self)) + } + } +} + + +#[test] +fn test_local_syntax_ptr() { + let file = File::parse("struct Foo { f: u32, }"); + let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap(); + let ptr = LocalSyntaxPtr::new(field.syntax()); + let field_syntax = ptr.resolve(&file); + assert_eq!(field.syntax(), field_syntax); +} diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 7efebab8b..043c9bacd 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml @@ -11,6 +11,7 @@ itertools = "0.7.8" drop_bomb = "0.1.4" parking_lot = "0.6.0" rowan = "0.1.1" +text_unit = "0.1.5" [dev-dependencies] test_utils = { path = "../test_utils" } -- cgit v1.2.3 From 1643d94a65a66f32b9278829dd3af00883f3852b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Oct 2018 21:26:55 +0300 Subject: switch to TextRange::subrange --- crates/ra_analysis/src/descriptors/mod.rs | 3 +-- crates/ra_editor/src/completion.rs | 3 +-- crates/ra_syntax/src/algo/mod.rs | 4 ++-- crates/ra_syntax/src/text_utils.rs | 4 ---- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index 873eb47e4..0220f7d5d 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs @@ -2,7 +2,6 @@ pub(crate) mod module; use ra_syntax::{ ast::{self, AstNode, NameOwner}, - text_utils::is_subrange, }; #[derive(Debug, Clone)] @@ -23,7 +22,7 @@ impl FnDescriptor { let label: String = node .syntax() .children() - .filter(|child| !is_subrange(body_range, child.range())) + .filter(|child| !child.range().is_subrange(&body_range)) .map(|node| node.text().to_string()) .collect(); label diff --git a/crates/ra_editor/src/completion.rs b/crates/ra_editor/src/completion.rs index 0a3675255..a0b168bc6 100644 --- a/crates/ra_editor/src/completion.rs +++ b/crates/ra_editor/src/completion.rs @@ -3,7 +3,6 @@ use rustc_hash::{FxHashMap, FxHashSet}; use ra_syntax::{ algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, - text_utils::is_subrange, AstNode, File, SyntaxKind::*, SyntaxNodeRef, TextUnit, @@ -191,7 +190,7 @@ fn is_in_loop_body(name_ref: ast::NameRef) -> bool { .visit::(LoopBodyOwner::loop_body) .accept(node); if let Some(Some(body)) = loop_body { - if is_subrange(body.syntax().range(), name_ref.syntax().range()) { + if name_ref.syntax().range().is_subrange(&body.syntax().range()) { return true; } } diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs index d82c42b3e..f92529d3e 100644 --- a/crates/ra_syntax/src/algo/mod.rs +++ b/crates/ra_syntax/src/algo/mod.rs @@ -2,7 +2,7 @@ pub mod visit; // pub mod walk; use crate::{ - text_utils::{contains_offset_nonstrict, is_subrange}, + text_utils::{contains_offset_nonstrict}, SyntaxNodeRef, TextRange, TextUnit, }; @@ -91,7 +91,7 @@ impl<'f> Iterator for LeafAtOffset<'f> { pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { assert!( - is_subrange(root.range(), range), + range.is_subrange(&root.range()), "node range: {:?}, target range: {:?}", root.range(), range, diff --git a/crates/ra_syntax/src/text_utils.rs b/crates/ra_syntax/src/text_utils.rs index abda5ec39..a90f8a083 100644 --- a/crates/ra_syntax/src/text_utils.rs +++ b/crates/ra_syntax/src/text_utils.rs @@ -4,10 +4,6 @@ pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { range.start() <= offset && offset <= range.end() } -pub fn is_subrange(range: TextRange, subrange: TextRange) -> bool { - range.start() <= subrange.start() && subrange.end() <= range.end() -} - pub fn intersect(r1: TextRange, r2: TextRange) -> Option { let start = r1.start().max(r2.start()); let end = r1.end().min(r2.end()); -- cgit v1.2.3