aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/call_info.rs2
-rw-r--r--crates/ra_analysis/src/completion/completion_context.rs3
-rw-r--r--crates/ra_analysis/src/db.rs24
-rw-r--r--crates/ra_analysis/src/goto_defenition.rs7
-rw-r--r--crates/ra_analysis/src/hover.rs3
-rw-r--r--crates/ra_analysis/src/imp.rs3
-rw-r--r--crates/ra_analysis/src/lib.rs17
-rw-r--r--crates/ra_db/Cargo.toml1
-rw-r--r--crates/ra_db/src/lib.rs10
-rw-r--r--crates/ra_editor/src/assists.rs4
-rw-r--r--crates/ra_editor/src/lib.rs4
-rw-r--r--crates/ra_editor/src/typing.rs4
-rw-r--r--crates/ra_hir/Cargo.toml1
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs3
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir/src/ty.rs1
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/conv.rs2
-rw-r--r--crates/ra_syntax/src/algo.rs15
20 files changed, 60 insertions, 48 deletions
diff --git a/crates/ra_analysis/src/call_info.rs b/crates/ra_analysis/src/call_info.rs
index 1dac95584..27b760780 100644
--- a/crates/ra_analysis/src/call_info.rs
+++ b/crates/ra_analysis/src/call_info.rs
@@ -5,8 +5,8 @@ use ra_syntax::{
5 AstNode, SyntaxNode, TextUnit, TextRange, 5 AstNode, SyntaxNode, TextUnit, TextRange,
6 SyntaxKind::FN_DEF, 6 SyntaxKind::FN_DEF,
7 ast::{self, ArgListOwner, DocCommentsOwner}, 7 ast::{self, ArgListOwner, DocCommentsOwner},
8 algo::find_node_at_offset,
8}; 9};
9use ra_editor::find_node_at_offset;
10 10
11use crate::{FilePosition, CallInfo, db::RootDatabase}; 11use crate::{FilePosition, CallInfo, db::RootDatabase};
12 12
diff --git a/crates/ra_analysis/src/completion/completion_context.rs b/crates/ra_analysis/src/completion/completion_context.rs
index 988c21c58..01786bb69 100644
--- a/crates/ra_analysis/src/completion/completion_context.rs
+++ b/crates/ra_analysis/src/completion/completion_context.rs
@@ -1,9 +1,8 @@
1use ra_editor::find_node_at_offset;
2use ra_text_edit::AtomTextEdit; 1use ra_text_edit::AtomTextEdit;
3use ra_syntax::{ 2use ra_syntax::{
4 AstNode, SyntaxNode, SourceFile, TextUnit, TextRange, 3 AstNode, SyntaxNode, SourceFile, TextUnit, TextRange,
5 ast, 4 ast,
6 algo::{find_leaf_at_offset, find_covering_node}, 5 algo::{find_leaf_at_offset, find_covering_node, find_node_at_offset},
7 SyntaxKind::*, 6 SyntaxKind::*,
8}; 7};
9use hir::source_binder; 8use hir::source_binder;
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 1709be5cf..9d46609ec 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,10 +1,9 @@
1use std::{fmt, sync::Arc}; 1use std::{fmt, sync::Arc};
2
2use salsa::{self, Database}; 3use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase}; 4use ra_db::{LocationIntener, BaseDatabase, FileId};
4 5
5use crate::{ 6use crate::{symbol_index, LineIndex};
6 symbol_index,
7};
8 7
9#[derive(Debug)] 8#[derive(Debug)]
10pub(crate) struct RootDatabase { 9pub(crate) struct RootDatabase {
@@ -71,6 +70,19 @@ impl AsRef<LocationIntener<hir::MacroCallLoc, hir::MacroCallId>> for RootDatabas
71 } 70 }
72} 71}
73 72
73salsa::query_group! {
74 pub(crate) trait LineIndexDatabase: ra_db::FilesDatabase + BaseDatabase {
75 fn line_index(file_id: FileId) -> Arc<LineIndex> {
76 type LineIndexQuery;
77 }
78 }
79}
80
81fn line_index(db: &impl ra_db::FilesDatabase, file_id: FileId) -> Arc<LineIndex> {
82 let text = db.file_text(file_id);
83 Arc::new(LineIndex::new(&*text))
84}
85
74salsa::database_storage! { 86salsa::database_storage! {
75 pub(crate) struct RootDatabaseStorage for RootDatabase { 87 pub(crate) struct RootDatabaseStorage for RootDatabase {
76 impl ra_db::FilesDatabase { 88 impl ra_db::FilesDatabase {
@@ -84,7 +96,9 @@ salsa::database_storage! {
84 } 96 }
85 impl ra_db::SyntaxDatabase { 97 impl ra_db::SyntaxDatabase {
86 fn source_file() for ra_db::SourceFileQuery; 98 fn source_file() for ra_db::SourceFileQuery;
87 fn file_lines() for ra_db::FileLinesQuery; 99 }
100 impl LineIndexDatabase {
101 fn line_index() for LineIndexQuery;
88 } 102 }
89 impl symbol_index::SymbolsDatabase { 103 impl symbol_index::SymbolsDatabase {
90 fn file_symbols() for symbol_index::FileSymbolsQuery; 104 fn file_symbols() for symbol_index::FileSymbolsQuery;
diff --git a/crates/ra_analysis/src/goto_defenition.rs b/crates/ra_analysis/src/goto_defenition.rs
index 0bcf13ebd..fcd8d315e 100644
--- a/crates/ra_analysis/src/goto_defenition.rs
+++ b/crates/ra_analysis/src/goto_defenition.rs
@@ -1,7 +1,8 @@
1use ra_db::{FileId, Cancelable, SyntaxDatabase}; 1use ra_db::{FileId, Cancelable, SyntaxDatabase};
2use ra_syntax::{TextRange, AstNode, ast, SyntaxKind::{NAME, MODULE}}; 2use ra_syntax::{
3 3 TextRange, AstNode, ast, SyntaxKind::{NAME, MODULE},
4use ra_editor::find_node_at_offset; 4 algo::find_node_at_offset,
5};
5 6
6use crate::{FilePosition, NavigationTarget, db::RootDatabase}; 7use crate::{FilePosition, NavigationTarget, db::RootDatabase};
7 8
diff --git a/crates/ra_analysis/src/hover.rs b/crates/ra_analysis/src/hover.rs
index 5607c3ef3..475524ee1 100644
--- a/crates/ra_analysis/src/hover.rs
+++ b/crates/ra_analysis/src/hover.rs
@@ -1,9 +1,8 @@
1use ra_db::{Cancelable, SyntaxDatabase}; 1use ra_db::{Cancelable, SyntaxDatabase};
2use ra_editor::find_node_at_offset;
3use ra_syntax::{ 2use ra_syntax::{
4 AstNode, SyntaxNode, TreePtr, 3 AstNode, SyntaxNode, TreePtr,
5 ast::{self, NameOwner}, 4 ast::{self, NameOwner},
6 algo::{find_covering_node, find_leaf_at_offset, visit::{visitor, Visitor}}, 5 algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}},
7}; 6};
8 7
9use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; 8use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget};
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index b3f75fdbe..2b9963b3c 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -6,10 +6,11 @@ use hir::{
6 self, Problem, source_binder, 6 self, Problem, source_binder,
7}; 7};
8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; 8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase};
9use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity}; 9use ra_editor::{self, assists, LocalEdit, Severity};
10use ra_syntax::{ 10use ra_syntax::{
11 TextRange, AstNode, SourceFile, 11 TextRange, AstNode, SourceFile,
12 ast::{self, NameOwner}, 12 ast::{self, NameOwner},
13 algo::find_node_at_offset,
13 SyntaxKind::*, 14 SyntaxKind::*,
14}; 15};
15 16
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 771a349c8..48df08416 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -29,22 +29,27 @@ use std::{fmt, sync::Arc};
29 29
30use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, TextRange, TextUnit}; 30use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, TextRange, TextUnit};
31use ra_text_edit::TextEdit; 31use ra_text_edit::TextEdit;
32use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr};
32use rayon::prelude::*; 33use rayon::prelude::*;
33use relative_path::RelativePathBuf; 34use relative_path::RelativePathBuf;
34use rustc_hash::FxHashMap; 35use rustc_hash::FxHashMap;
35use salsa::ParallelDatabase; 36use salsa::ParallelDatabase;
36 37
37use crate::symbol_index::{FileSymbol, SymbolIndex}; 38use crate::{
39 symbol_index::{FileSymbol, SymbolIndex},
40 db::LineIndexDatabase,
41};
38 42
39pub use crate::{ 43pub use crate::{
40 completion::{CompletionItem, CompletionItemKind, InsertText}, 44 completion::{CompletionItem, CompletionItemKind, InsertText},
41 runnables::{Runnable, RunnableKind}, 45 runnables::{Runnable, RunnableKind},
42}; 46};
43pub use ra_editor::{Fold, FoldKind, HighlightedRange, LineIndex, Severity, StructureNode}; 47pub use ra_editor::{
44 48 Fold, FoldKind, HighlightedRange, Severity, StructureNode,
49 LineIndex, LineCol, translate_offset_with_edit,
50};
45pub use ra_db::{ 51pub use ra_db::{
46 Cancelable, Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, FilesDatabase, 52 Cancelable, Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId
47 LocalSyntaxPtr, SourceRootId, SyntaxDatabase,
48}; 53};
49 54
50#[derive(Default)] 55#[derive(Default)]
@@ -322,7 +327,7 @@ impl Analysis {
322 /// Gets the file's `LineIndex`: data structure to convert between absolute 327 /// Gets the file's `LineIndex`: data structure to convert between absolute
323 /// offsets and line/column representation. 328 /// offsets and line/column representation.
324 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 329 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
325 self.db.file_lines(file_id) 330 self.db.line_index(file_id)
326 } 331 }
327 /// Selects the next syntactic nodes encopasing the range. 332 /// Selects the next syntactic nodes encopasing the range.
328 pub fn extend_selection(&self, frange: FileRange) -> TextRange { 333 pub fn extend_selection(&self, frange: FileRange) -> TextRange {
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index c43e65051..2c1f94ad0 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -11,5 +11,4 @@ rustc-hash = "1.0"
11parking_lot = "0.7.0" 11parking_lot = "0.7.0"
12ra_arena = { path = "../ra_arena" } 12ra_arena = { path = "../ra_arena" }
13ra_syntax = { path = "../ra_syntax" } 13ra_syntax = { path = "../ra_syntax" }
14ra_editor = { path = "../ra_editor" }
15test_utils = { path = "../test_utils" } 14test_utils = { path = "../test_utils" }
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 732899718..f56f70983 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -5,9 +5,6 @@ mod input;
5mod loc2id; 5mod loc2id;
6pub mod mock; 6pub mod mock;
7 7
8use std::sync::Arc;
9
10use ra_editor::LineIndex;
11use ra_syntax::{TextUnit, TextRange, SourceFile, TreePtr}; 8use ra_syntax::{TextUnit, TextRange, SourceFile, TreePtr};
12 9
13pub use crate::{ 10pub use crate::{
@@ -36,9 +33,6 @@ salsa::query_group! {
36 fn source_file(file_id: FileId) -> TreePtr<SourceFile> { 33 fn source_file(file_id: FileId) -> TreePtr<SourceFile> {
37 type SourceFileQuery; 34 type SourceFileQuery;
38 } 35 }
39 fn file_lines(file_id: FileId) -> Arc<LineIndex> {
40 type FileLinesQuery;
41 }
42 } 36 }
43} 37}
44 38
@@ -46,10 +40,6 @@ fn source_file(db: &impl SyntaxDatabase, file_id: FileId) -> TreePtr<SourceFile>
46 let text = db.file_text(file_id); 40 let text = db.file_text(file_id);
47 SourceFile::parse(&*text) 41 SourceFile::parse(&*text)
48} 42}
49fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
50 let text = db.file_text(file_id);
51 Arc::new(LineIndex::new(&*text))
52}
53 43
54#[derive(Clone, Copy, Debug)] 44#[derive(Clone, Copy, Debug)]
55pub struct FilePosition { 45pub struct FilePosition {
diff --git a/crates/ra_editor/src/assists.rs b/crates/ra_editor/src/assists.rs
index f839f6a7a..83eabfc85 100644
--- a/crates/ra_editor/src/assists.rs
+++ b/crates/ra_editor/src/assists.rs
@@ -14,13 +14,11 @@ mod replace_if_let_with_match;
14use ra_text_edit::{TextEdit, TextEditBuilder}; 14use ra_text_edit::{TextEdit, TextEditBuilder};
15use ra_syntax::{ 15use ra_syntax::{
16 Direction, SyntaxNode, TextUnit, TextRange, SourceFile, AstNode, 16 Direction, SyntaxNode, TextUnit, TextRange, SourceFile, AstNode,
17 algo::{find_leaf_at_offset, find_covering_node, LeafAtOffset}, 17 algo::{find_leaf_at_offset, find_node_at_offset, find_covering_node, LeafAtOffset},
18 ast::{self, AstToken}, 18 ast::{self, AstToken},
19}; 19};
20use itertools::Itertools; 20use itertools::Itertools;
21 21
22use crate::find_node_at_offset;
23
24pub use self::{ 22pub use self::{
25 flip_comma::flip_comma, 23 flip_comma::flip_comma,
26 add_derive::add_derive, 24 add_derive::add_derive,
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index 6731260a3..5a6af19b7 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -120,10 +120,6 @@ pub fn syntax_tree(file: &SourceFile) -> String {
120 ::ra_syntax::utils::dump_tree(file.syntax()) 120 ::ra_syntax::utils::dump_tree(file.syntax())
121} 121}
122 122
123pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> {
124 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast))
125}
126
127#[cfg(test)] 123#[cfg(test)]
128mod tests { 124mod tests {
129 use ra_syntax::AstNode; 125 use ra_syntax::AstNode;
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 5b260d2ac..576caf6be 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -2,7 +2,7 @@ use std::mem;
2 2
3use itertools::Itertools; 3use itertools::Itertools;
4use ra_syntax::{ 4use ra_syntax::{
5 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, 5 algo::{find_node_at_offset, find_covering_node, find_leaf_at_offset, LeafAtOffset},
6 ast, 6 ast,
7 text_utils::intersect, 7 text_utils::intersect,
8 AstNode, Direction, SourceFile, SyntaxKind, 8 AstNode, Direction, SourceFile, SyntaxKind,
@@ -11,7 +11,7 @@ use ra_syntax::{
11}; 11};
12use ra_text_edit::text_utils::contains_offset_nonstrict; 12use ra_text_edit::text_utils::contains_offset_nonstrict;
13 13
14use crate::{find_node_at_offset, LocalEdit, TextEditBuilder}; 14use crate::{LocalEdit, TextEditBuilder};
15 15
16pub fn join_lines(file: &SourceFile, range: TextRange) -> LocalEdit { 16pub fn join_lines(file: &SourceFile, range: TextRange) -> LocalEdit {
17 let range = if range.is_empty() { 17 let range = if range.is_empty() {
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 245a21ce3..5a8fdbfc6 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -14,7 +14,6 @@ parking_lot = "0.7.0"
14ena = "0.11" 14ena = "0.11"
15ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
16ra_arena = { path = "../ra_arena" } 16ra_arena = { path = "../ra_arena" }
17ra_editor = { path = "../ra_editor" }
18ra_db = { path = "../ra_db" } 17ra_db = { path = "../ra_db" }
19test_utils = { path = "../test_utils" } 18test_utils = { path = "../test_utils" }
20 19
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs
index 699784f71..ebf6edc1b 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/code_model_impl/function/scope.rs
@@ -308,8 +308,7 @@ pub struct ReferenceDescriptor {
308 308
309#[cfg(test)] 309#[cfg(test)]
310mod tests { 310mod tests {
311 use ra_editor::find_node_at_offset; 311 use ra_syntax::{SourceFile, algo::find_node_at_offset};
312 use ra_syntax::SourceFile;
313 use test_utils::{extract_offset, assert_eq_text}; 312 use test_utils::{extract_offset, assert_eq_text};
314 313
315 use crate::expr; 314 use crate::expr;
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index c9af38009..0fae7de82 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -215,7 +215,6 @@ salsa::database_storage! {
215 } 215 }
216 impl ra_db::SyntaxDatabase { 216 impl ra_db::SyntaxDatabase {
217 fn source_file() for ra_db::SourceFileQuery; 217 fn source_file() for ra_db::SourceFileQuery;
218 fn file_lines() for ra_db::FileLinesQuery;
219 } 218 }
220 impl db::HirDatabase { 219 impl db::HirDatabase {
221 fn hir_source_file() for db::HirSourceFileQuery; 220 fn hir_source_file() for db::HirSourceFileQuery;
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 59a803761..4b0400cd0 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -6,10 +6,10 @@
6/// So, this modules should not be used during hir construction, it exists 6/// So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs". 7/// purely for "IDE needs".
8use ra_db::{FileId, FilePosition, Cancelable}; 8use ra_db::{FileId, FilePosition, Cancelable};
9use ra_editor::find_node_at_offset;
10use ra_syntax::{ 9use ra_syntax::{
11 SmolStr, TextRange, SyntaxNode, 10 SmolStr, TextRange, SyntaxNode,
12 ast::{self, AstNode, NameOwner}, 11 ast::{self, AstNode, NameOwner},
12 algo::find_node_at_offset,
13}; 13};
14 14
15use crate::{ 15use crate::{
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 8adeedddb..90ba393ce 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -1049,6 +1049,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1049} 1049}
1050 1050
1051pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 1051pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> {
1052 db.check_canceled()?;
1052 let function = Function::new(def_id); // TODO: consts also need inference 1053 let function = Function::new(def_id); // TODO: consts also need inference
1053 let body = function.body(db)?; 1054 let body = function.body(db)?;
1054 let scopes = db.fn_scopes(def_id)?; 1055 let scopes = db.fn_scopes(def_id)?;
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 8bd4caa53..b9fd61105 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -28,7 +28,6 @@ parking_lot = "0.7.0"
28 28
29thread_worker = { path = "../thread_worker" } 29thread_worker = { path = "../thread_worker" }
30ra_syntax = { path = "../ra_syntax" } 30ra_syntax = { path = "../ra_syntax" }
31ra_editor = { path = "../ra_editor" }
32ra_text_edit = { path = "../ra_text_edit" } 31ra_text_edit = { path = "../ra_text_edit" }
33ra_analysis = { path = "../ra_analysis" } 32ra_analysis = { path = "../ra_analysis" }
34gen_lsp_server = { path = "../gen_lsp_server" } 33gen_lsp_server = { path = "../gen_lsp_server" }
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index e8eb3940f..b3f8c83cc 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -7,8 +7,8 @@ use languageserver_types::{
7use ra_analysis::{ 7use ra_analysis::{
8 CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit, 8 CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit,
9 InsertText, NavigationTarget, SourceChange, SourceFileEdit, 9 InsertText, NavigationTarget, SourceChange, SourceFileEdit,
10 LineCol, LineIndex, translate_offset_with_edit
10}; 11};
11use ra_editor::{translate_offset_with_edit, LineCol, LineIndex};
12use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 12use ra_syntax::{SyntaxKind, TextRange, TextUnit};
13use ra_text_edit::{AtomTextEdit, TextEdit}; 13use ra_text_edit::{AtomTextEdit, TextEdit};
14 14
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index 13f50d2ef..45747e21d 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -2,7 +2,7 @@ pub mod visit;
2 2
3use rowan::TransparentNewType; 3use rowan::TransparentNewType;
4 4
5use crate::{SyntaxNode, TextRange, TextUnit}; 5use crate::{SyntaxNode, TextRange, TextUnit, AstNode};
6 6
7pub use rowan::LeafAtOffset; 7pub use rowan::LeafAtOffset;
8 8
@@ -16,6 +16,19 @@ pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset<
16 } 16 }
17} 17}
18 18
19/// Finds a node of specific Ast type at offset. Note that this is slightly
20/// impercise: if the cursor is strictly betwen two nodes of the desired type,
21/// as in
22///
23/// ```no-run
24/// struct Foo {}|struct Bar;
25/// ```
26///
27/// then the left node will be silently prefered.
28pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> {
29 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast))
30}
31
19pub fn find_covering_node(root: &SyntaxNode, range: TextRange) -> &SyntaxNode { 32pub fn find_covering_node(root: &SyntaxNode, range: TextRange) -> &SyntaxNode {
20 SyntaxNode::from_repr(root.0.covering_node(range)) 33 SyntaxNode::from_repr(root.0.covering_node(range))
21} 34}