diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/src/descriptors/mod.rs | 3 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_analysis/src/syntax_ptr.rs | 67 | ||||
-rw-r--r-- | crates/ra_editor/src/completion.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/algo/mod.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/text_utils.rs | 4 |
7 files changed, 73 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; | |||
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | ast::{self, AstNode, NameOwner}, | 4 | ast::{self, AstNode, NameOwner}, |
5 | text_utils::is_subrange, | ||
6 | }; | 5 | }; |
7 | 6 | ||
8 | #[derive(Debug, Clone)] | 7 | #[derive(Debug, Clone)] |
@@ -23,7 +22,7 @@ impl FnDescriptor { | |||
23 | let label: String = node | 22 | let label: String = node |
24 | .syntax() | 23 | .syntax() |
25 | .children() | 24 | .children() |
26 | .filter(|child| !is_subrange(body_range, child.range())) | 25 | .filter(|child| !child.range().is_subrange(&body_range)) |
27 | .map(|node| node.text().to_string()) | 26 | .map(|node| node.text().to_string()) |
28 | .collect(); | 27 | .collect(); |
29 | label | 28 | label |
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; | |||
12 | mod imp; | 12 | mod imp; |
13 | mod symbol_index; | 13 | mod symbol_index; |
14 | mod completion; | 14 | mod completion; |
15 | mod syntax_ptr; | ||
15 | 16 | ||
16 | use std::{ | 17 | use 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 @@ | |||
1 | use ra_syntax::{ | ||
2 | File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef, | ||
3 | ast::{self, AstNode}, | ||
4 | }; | ||
5 | |||
6 | use crate::FileId; | ||
7 | use 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)] | ||
13 | pub(crate) struct SyntaxPtr { | ||
14 | file_id: FileId, | ||
15 | local: LocalSyntaxPtr, | ||
16 | } | ||
17 | |||
18 | impl 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)] | ||
33 | struct LocalSyntaxPtr { | ||
34 | range: TextRange, | ||
35 | kind: SyntaxKind, | ||
36 | } | ||
37 | |||
38 | impl 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] | ||
61 | fn 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 | } | ||
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}; | |||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, | 4 | algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, |
5 | ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, | 5 | ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, |
6 | text_utils::is_subrange, | ||
7 | AstNode, File, | 6 | AstNode, File, |
8 | SyntaxKind::*, | 7 | SyntaxKind::*, |
9 | SyntaxNodeRef, TextUnit, | 8 | SyntaxNodeRef, TextUnit, |
@@ -191,7 +190,7 @@ fn is_in_loop_body(name_ref: ast::NameRef) -> bool { | |||
191 | .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body) | 190 | .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body) |
192 | .accept(node); | 191 | .accept(node); |
193 | if let Some(Some(body)) = loop_body { | 192 | if let Some(Some(body)) = loop_body { |
194 | if is_subrange(body.syntax().range(), name_ref.syntax().range()) { | 193 | if name_ref.syntax().range().is_subrange(&body.syntax().range()) { |
195 | return true; | 194 | return true; |
196 | } | 195 | } |
197 | } | 196 | } |
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" | |||
11 | drop_bomb = "0.1.4" | 11 | drop_bomb = "0.1.4" |
12 | parking_lot = "0.6.0" | 12 | parking_lot = "0.6.0" |
13 | rowan = "0.1.1" | 13 | rowan = "0.1.1" |
14 | text_unit = "0.1.5" | ||
14 | 15 | ||
15 | [dev-dependencies] | 16 | [dev-dependencies] |
16 | test_utils = { path = "../test_utils" } | 17 | test_utils = { path = "../test_utils" } |
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; | |||
2 | // pub mod walk; | 2 | // pub mod walk; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | text_utils::{contains_offset_nonstrict, is_subrange}, | 5 | text_utils::{contains_offset_nonstrict}, |
6 | SyntaxNodeRef, TextRange, TextUnit, | 6 | SyntaxNodeRef, TextRange, TextUnit, |
7 | }; | 7 | }; |
8 | 8 | ||
@@ -91,7 +91,7 @@ impl<'f> Iterator for LeafAtOffset<'f> { | |||
91 | 91 | ||
92 | pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { | 92 | pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { |
93 | assert!( | 93 | assert!( |
94 | is_subrange(root.range(), range), | 94 | range.is_subrange(&root.range()), |
95 | "node range: {:?}, target range: {:?}", | 95 | "node range: {:?}, target range: {:?}", |
96 | root.range(), | 96 | root.range(), |
97 | range, | 97 | 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 { | |||
4 | range.start() <= offset && offset <= range.end() | 4 | range.start() <= offset && offset <= range.end() |
5 | } | 5 | } |
6 | 6 | ||
7 | pub fn is_subrange(range: TextRange, subrange: TextRange) -> bool { | ||
8 | range.start() <= subrange.start() && subrange.end() <= range.end() | ||
9 | } | ||
10 | |||
11 | pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> { | 7 | pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> { |
12 | let start = r1.start().max(r2.start()); | 8 | let start = r1.start().max(r2.start()); |
13 | let end = r1.end().min(r2.end()); | 9 | let end = r1.end().min(r2.end()); |