diff options
Diffstat (limited to 'crates/ra_analysis/src/syntax_ptr.rs')
-rw-r--r-- | crates/ra_analysis/src/syntax_ptr.rs | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_analysis/src/syntax_ptr.rs index 863ad2672..adbff4806 100644 --- a/crates/ra_analysis/src/syntax_ptr.rs +++ b/crates/ra_analysis/src/syntax_ptr.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use std::marker::PhantomData; | ||
2 | |||
1 | use ra_syntax::{ | 3 | use ra_syntax::{ |
2 | File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef, | 4 | File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef, |
3 | ast::{self, AstNode}, | 5 | ast::{self, AstNode}, |
@@ -6,10 +8,24 @@ use ra_syntax::{ | |||
6 | use crate::FileId; | 8 | use crate::FileId; |
7 | use crate::db::SyntaxDatabase; | 9 | use crate::db::SyntaxDatabase; |
8 | 10 | ||
11 | salsa::query_group! { | ||
12 | pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase { | ||
13 | fn resolve_syntax_ptr(ptr: SyntaxPtr) -> SyntaxNode { | ||
14 | type ResolveSyntaxPtrQuery; | ||
15 | storage volatile; | ||
16 | } | ||
17 | } | ||
18 | } | ||
19 | |||
20 | fn resolve_syntax_ptr(db: &impl SyntaxDatabase, ptr: SyntaxPtr) -> SyntaxNode { | ||
21 | let syntax = db.file_syntax(ptr.file_id); | ||
22 | ptr.local.resolve(&syntax) | ||
23 | } | ||
24 | |||
9 | /// SyntaxPtr is a cheap `Copy` id which identifies a particular syntax node, | 25 | /// SyntaxPtr is a cheap `Copy` id which identifies a particular syntax node, |
10 | /// without retainig syntax tree in memory. You need to explicitelly `resovle` | 26 | /// without retainig syntax tree in memory. You need to explicitelly `resovle` |
11 | /// `SyntaxPtr` to get a `SyntaxNode` | 27 | /// `SyntaxPtr` to get a `SyntaxNode` |
12 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 28 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
13 | pub(crate) struct SyntaxPtr { | 29 | pub(crate) struct SyntaxPtr { |
14 | file_id: FileId, | 30 | file_id: FileId, |
15 | local: LocalSyntaxPtr, | 31 | local: LocalSyntaxPtr, |
@@ -20,30 +36,43 @@ impl SyntaxPtr { | |||
20 | let local = LocalSyntaxPtr::new(node); | 36 | let local = LocalSyntaxPtr::new(node); |
21 | SyntaxPtr { file_id, local } | 37 | SyntaxPtr { file_id, local } |
22 | } | 38 | } |
39 | } | ||
40 | |||
41 | struct OwnedAst<T> { | ||
42 | syntax: SyntaxNode, | ||
43 | phantom: PhantomData<T>, | ||
44 | } | ||
45 | |||
46 | trait ToAst { | ||
47 | type Ast; | ||
48 | fn to_ast(self) -> Self::Ast; | ||
49 | } | ||
23 | 50 | ||
24 | pub(crate) fn resolve(self, db: &impl SyntaxDatabase) -> SyntaxNode { | 51 | impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> { |
25 | let syntax = db.file_syntax(self.file_id); | 52 | type Ast = ast::FnDef<'a>; |
26 | self.local.resolve(&syntax) | 53 | fn to_ast(self) -> ast::FnDef<'a> { |
54 | ast::FnDef::cast(self.syntax.borrowed()) | ||
55 | .unwrap() | ||
27 | } | 56 | } |
28 | } | 57 | } |
29 | 58 | ||
30 | 59 | ||
31 | /// A pionter to a syntax node inside a file. | 60 | /// A pionter to a syntax node inside a file. |
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 61 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
33 | struct LocalSyntaxPtr { | 62 | pub(crate) struct LocalSyntaxPtr { |
34 | range: TextRange, | 63 | range: TextRange, |
35 | kind: SyntaxKind, | 64 | kind: SyntaxKind, |
36 | } | 65 | } |
37 | 66 | ||
38 | impl LocalSyntaxPtr { | 67 | impl LocalSyntaxPtr { |
39 | fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr { | 68 | pub(crate) fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr { |
40 | LocalSyntaxPtr { | 69 | LocalSyntaxPtr { |
41 | range: node.range(), | 70 | range: node.range(), |
42 | kind: node.kind(), | 71 | kind: node.kind(), |
43 | } | 72 | } |
44 | } | 73 | } |
45 | 74 | ||
46 | fn resolve(self, file: &File) -> SyntaxNode { | 75 | pub(crate) fn resolve(self, file: &File) -> SyntaxNode { |
47 | let mut curr = file.syntax(); | 76 | let mut curr = file.syntax(); |
48 | loop { | 77 | loop { |
49 | if curr.range() == self.range && curr.kind() == self.kind { | 78 | if curr.range() == self.range && curr.kind() == self.kind { |