aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r--crates/ra_analysis/src/completion/complete_dot.rs15
-rw-r--r--crates/ra_analysis/src/db.rs1
-rw-r--r--crates/ra_analysis/src/goto_defenition.rs73
-rw-r--r--crates/ra_analysis/src/imp.rs40
-rw-r--r--crates/ra_analysis/src/lib.rs13
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs7
-rw-r--r--crates/ra_analysis/src/symbol_index.rs78
-rw-r--r--crates/ra_analysis/src/syntax_highlighting.rs10
8 files changed, 170 insertions, 67 deletions
diff --git a/crates/ra_analysis/src/completion/complete_dot.rs b/crates/ra_analysis/src/completion/complete_dot.rs
index f24835d17..031d8b98f 100644
--- a/crates/ra_analysis/src/completion/complete_dot.rs
+++ b/crates/ra_analysis/src/completion/complete_dot.rs
@@ -73,6 +73,21 @@ mod tests {
73 } 73 }
74 74
75 #[test] 75 #[test]
76 fn test_struct_field_completion_self() {
77 check_ref_completion(
78 r"
79 struct A { the_field: u32 }
80 impl A {
81 fn foo(self) {
82 self.<|>
83 }
84 }
85 ",
86 r#"the_field"#,
87 );
88 }
89
90 #[test]
76 fn test_no_struct_field_completion_for_method_call() { 91 fn test_no_struct_field_completion_for_method_call() {
77 check_ref_completion( 92 check_ref_completion(
78 r" 93 r"
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index d7740f0c4..5422a400b 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -105,6 +105,7 @@ salsa::database_storage! {
105 fn type_for_field() for hir::db::TypeForFieldQuery; 105 fn type_for_field() for hir::db::TypeForFieldQuery;
106 fn struct_data() for hir::db::StructDataQuery; 106 fn struct_data() for hir::db::StructDataQuery;
107 fn enum_data() for hir::db::EnumDataQuery; 107 fn enum_data() for hir::db::EnumDataQuery;
108 fn impls_in_module() for hir::db::ImplsInModuleQuery;
108 } 109 }
109 } 110 }
110} 111}
diff --git a/crates/ra_analysis/src/goto_defenition.rs b/crates/ra_analysis/src/goto_defenition.rs
new file mode 100644
index 000000000..607a25115
--- /dev/null
+++ b/crates/ra_analysis/src/goto_defenition.rs
@@ -0,0 +1,73 @@
1use ra_db::FileId;
2use ra_syntax::ast;
3
4use crate::db::RootDatabase;
5
6pub fn goto_defenition(db: &RootDatabase, position: FilePosition,
7) -> Cancelable<Option<Vec<NavigationTarget>>> {
8 let file = db.source_file(position.file_id);
9 let syntax = file.syntax();
10 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
11 return Ok(Some(reference_defenition(db, position.file_id, name_ref)));
12 }
13 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
14 return Ok(Some(name_defenition(db, position.file_idname)));
15 }
16 Ok(None)
17}
18
19fn reference_defenition(db: &RootDatabase, file_id: FileId, name_ref: ast::NameRef) -> Cancelable<Vec<Nav>> {
20 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
21 let mut rr = ReferenceResolution::new(name_ref.syntax().range());
22 if let Some(fn_descr) =
23 source_binder::function_from_child_node(self, position.file_id, name_ref.syntax())?
24 {
25 let scope = fn_descr.scopes(self);
26 // First try to resolve the symbol locally
27 if let Some(entry) = scope.resolve_local_name(name_ref) {
28 rr.resolves_to.push(NavigationTarget {
29 file_id: position.file_id,
30 name: entry.name().to_string().into(),
31 range: entry.ptr().range(),
32 kind: NAME,
33 ptr: None,
34 });
35 return Ok(Some(rr));
36 };
37 }
38 // If that fails try the index based approach.
39 rr.resolves_to.extend(
40 self.index_resolve(name_ref)?
41 .into_iter()
42 .map(NavigationTarget::from_symbol),
43 );
44 return Ok(Some(rr));
45 }
46 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
47 let mut rr = ReferenceResolution::new(name.syntax().range());
48 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
49 if module.has_semi() {
50 if let Some(child_module) =
51 source_binder::module_from_declaration(self, position.file_id, module)?
52 {
53 let file_id = child_module.file_id();
54 let name = match child_module.name() {
55 Some(name) => name.to_string().into(),
56 None => "".into(),
57 };
58 let symbol = NavigationTarget {
59 file_id,
60 name,
61 range: TextRange::offset_len(0.into(), 0.into()),
62 kind: MODULE,
63 ptr: None,
64 };
65 rr.resolves_to.push(symbol);
66 return Ok(Some(rr));
67 }
68 }
69 }
70 }
71 Ok(None)
72
73}
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index b812c3441..eae73c2c4 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -6,7 +6,7 @@ use hir::{
6 self, FnSignatureInfo, Problem, source_binder, 6 self, FnSignatureInfo, 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, LocalEdit, Severity}; 9use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity};
10use ra_syntax::{ 10use ra_syntax::{
11 algo::{find_covering_node, visit::{visitor, Visitor}}, 11 algo::{find_covering_node, visit::{visitor, Visitor}},
12 ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, 12 ast::{self, ArgListOwner, Expr, FnDef, NameOwner},
@@ -165,9 +165,11 @@ impl db::RootDatabase {
165 }; 165 };
166 } 166 }
167 // If that fails try the index based approach. 167 // If that fails try the index based approach.
168 for (file_id, symbol) in self.index_resolve(name_ref)? { 168 rr.resolves_to.extend(
169 rr.add_resolution(file_id, symbol); 169 self.index_resolve(name_ref)?
170 } 170 .into_iter()
171 .map(NavigationTarget::from_symbol),
172 );
171 return Ok(Some(rr)); 173 return Ok(Some(rr));
172 } 174 }
173 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 175 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
@@ -333,19 +335,9 @@ impl db::RootDatabase {
333 335
334 pub(crate) fn assists(&self, frange: FileRange) -> Vec<SourceChange> { 336 pub(crate) fn assists(&self, frange: FileRange) -> Vec<SourceChange> {
335 let file = self.source_file(frange.file_id); 337 let file = self.source_file(frange.file_id);
336 let offset = frange.range.start(); 338 assists::assists(&file, frange.range)
337 let actions = vec![
338 ra_editor::flip_comma(&file, offset).map(|f| f()),
339 ra_editor::add_derive(&file, offset).map(|f| f()),
340 ra_editor::add_impl(&file, offset).map(|f| f()),
341 ra_editor::make_pub_crate(&file, offset).map(|f| f()),
342 ra_editor::introduce_variable(&file, frange.range).map(|f| f()),
343 ];
344 actions
345 .into_iter() 339 .into_iter()
346 .filter_map(|local_edit| { 340 .map(|local_edit| SourceChange::from_local_edit(frange.file_id, local_edit))
347 Some(SourceChange::from_local_edit(frange.file_id, local_edit?))
348 })
349 .collect() 341 .collect()
350 } 342 }
351 343
@@ -362,13 +354,15 @@ impl db::RootDatabase {
362 354
363 // Resolve the function's NameRef (NOTE: this isn't entirely accurate). 355 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
364 let file_symbols = self.index_resolve(name_ref)?; 356 let file_symbols = self.index_resolve(name_ref)?;
365 for (fn_file_id, fs) in file_symbols { 357 for symbol in file_symbols {
366 if fs.ptr.kind() == FN_DEF { 358 if symbol.ptr.kind() == FN_DEF {
367 let fn_file = self.source_file(fn_file_id); 359 let fn_file = self.source_file(symbol.file_id);
368 let fn_def = fs.ptr.resolve(&fn_file); 360 let fn_def = symbol.ptr.resolve(&fn_file);
369 let fn_def = ast::FnDef::cast(fn_def.borrowed()).unwrap(); 361 let fn_def = ast::FnDef::cast(fn_def.borrowed()).unwrap();
370 let descr = ctry!(source_binder::function_from_source( 362 let descr = ctry!(source_binder::function_from_source(
371 self, fn_file_id, fn_def 363 self,
364 symbol.file_id,
365 fn_def
372 )?); 366 )?);
373 if let Some(descriptor) = descr.signature_info(self) { 367 if let Some(descriptor) = descr.signature_info(self) {
374 // If we have a calling expression let's find which argument we are on 368 // If we have a calling expression let's find which argument we are on
@@ -440,7 +434,7 @@ impl db::RootDatabase {
440 .map(|(file_id, text_range)| SourceFileEdit { 434 .map(|(file_id, text_range)| SourceFileEdit {
441 file_id: *file_id, 435 file_id: *file_id,
442 edit: { 436 edit: {
443 let mut builder = ra_text_edit::TextEditBuilder::new(); 437 let mut builder = ra_text_edit::TextEditBuilder::default();
444 builder.replace(*text_range, new_name.into()); 438 builder.replace(*text_range, new_name.into());
445 builder.finish() 439 builder.finish()
446 }, 440 },
@@ -448,7 +442,7 @@ impl db::RootDatabase {
448 .collect::<Vec<_>>(); 442 .collect::<Vec<_>>();
449 Ok(res) 443 Ok(res)
450 } 444 }
451 fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<(FileId, FileSymbol)>> { 445 fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<FileSymbol>> {
452 let name = name_ref.text(); 446 let name = name_ref.text();
453 let mut query = Query::new(name.to_string()); 447 let mut query = Query::new(name.to_string());
454 query.exact(); 448 query.exact();
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 61af676b2..1e26a2889 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -237,11 +237,11 @@ pub struct NavigationTarget {
237} 237}
238 238
239impl NavigationTarget { 239impl NavigationTarget {
240 fn from_symbol(file_id: FileId, symbol: FileSymbol) -> NavigationTarget { 240 fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
241 NavigationTarget { 241 NavigationTarget {
242 file_id: symbol.file_id,
242 name: symbol.name.clone(), 243 name: symbol.name.clone(),
243 kind: symbol.ptr.kind(), 244 kind: symbol.ptr.kind(),
244 file_id,
245 range: symbol.ptr.range(), 245 range: symbol.ptr.range(),
246 ptr: Some(symbol.ptr.clone()), 246 ptr: Some(symbol.ptr.clone()),
247 } 247 }
@@ -278,11 +278,6 @@ impl ReferenceResolution {
278 resolves_to: Vec::new(), 278 resolves_to: Vec::new(),
279 } 279 }
280 } 280 }
281
282 fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
283 self.resolves_to
284 .push(NavigationTarget::from_symbol(file_id, symbol))
285 }
286} 281}
287 282
288/// `AnalysisHost` stores the current state of the world. 283/// `AnalysisHost` stores the current state of the world.
@@ -380,7 +375,7 @@ impl Analysis {
380 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { 375 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
381 let res = symbol_index::world_symbols(&*self.db, query)? 376 let res = symbol_index::world_symbols(&*self.db, query)?
382 .into_iter() 377 .into_iter()
383 .map(|(file_id, symbol)| NavigationTarget::from_symbol(file_id, symbol)) 378 .map(NavigationTarget::from_symbol)
384 .collect(); 379 .collect();
385 Ok(res) 380 Ok(res)
386 } 381 }
@@ -399,7 +394,7 @@ impl Analysis {
399 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { 394 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
400 self.db.doc_text_for(nav) 395 self.db.doc_text_for(nav)
401 } 396 }
402 /// Returns a `mod name;` declaration whihc created the current module. 397 /// Returns a `mod name;` declaration which created the current module.
403 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { 398 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
404 self.db.parent_module(position) 399 self.db.parent_module(position)
405 } 400 }
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs
index 960529404..846c76cfe 100644
--- a/crates/ra_analysis/src/mock_analysis.rs
+++ b/crates/ra_analysis/src/mock_analysis.rs
@@ -4,7 +4,7 @@ use relative_path::RelativePathBuf;
4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; 4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
5use ra_db::mock::FileMap; 5use ra_db::mock::FileMap;
6 6
7use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FilePosition, FileRange, SourceRootId}; 7use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId};
8 8
9/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis 9/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
10/// from a set of in-memory files. 10/// from a set of in-memory files.
@@ -87,12 +87,17 @@ impl MockAnalysis {
87 let source_root = SourceRootId(0); 87 let source_root = SourceRootId(0);
88 let mut change = AnalysisChange::new(); 88 let mut change = AnalysisChange::new();
89 change.add_root(source_root, true); 89 change.add_root(source_root, true);
90 let mut crate_graph = CrateGraph::default();
90 for (path, contents) in self.files.into_iter() { 91 for (path, contents) in self.files.into_iter() {
91 assert!(path.starts_with('/')); 92 assert!(path.starts_with('/'));
92 let path = RelativePathBuf::from_path(&path[1..]).unwrap(); 93 let path = RelativePathBuf::from_path(&path[1..]).unwrap();
93 let file_id = file_map.add(path.clone()); 94 let file_id = file_map.add(path.clone());
95 if path == "/lib.rs" || path == "/main.rs" {
96 crate_graph.add_crate_root(file_id);
97 }
94 change.add_file(source_root, file_id, path, Arc::new(contents)); 98 change.add_file(source_root, file_id, path, Arc::new(contents));
95 } 99 }
100 change.set_crate_graph(crate_graph);
96 // change.set_file_resolver(Arc::new(file_map)); 101 // change.set_file_resolver(Arc::new(file_map));
97 host.apply_change(change); 102 host.apply_change(change);
98 host 103 host
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index 10d8e8059..e2b1c88fe 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -20,6 +20,7 @@
20//! file in the current workspace, and run a query aginst the union of all 20//! file in the current workspace, and run a query aginst the union of all
21//! thouse fsts. 21//! thouse fsts.
22use std::{ 22use std::{
23 cmp::Ordering,
23 hash::{Hash, Hasher}, 24 hash::{Hash, Hasher},
24 sync::Arc, 25 sync::Arc,
25}; 26};
@@ -27,11 +28,11 @@ use std::{
27use fst::{self, Streamer}; 28use fst::{self, Streamer};
28use ra_syntax::{ 29use ra_syntax::{
29 SyntaxNodeRef, SourceFileNode, SmolStr, 30 SyntaxNodeRef, SourceFileNode, SmolStr,
30 algo::visit::{visitor, Visitor}, 31 algo::{visit::{visitor, Visitor}, find_covering_node},
31 SyntaxKind::{self, *}, 32 SyntaxKind::{self, *},
32 ast::{self, NameOwner}, 33 ast::{self, NameOwner},
33}; 34};
34use ra_db::{SyntaxDatabase, SourceRootId, FilesDatabase, LocalSyntaxPtr}; 35use ra_db::{SourceRootId, FilesDatabase, LocalSyntaxPtr};
35use salsa::ParallelDatabase; 36use salsa::ParallelDatabase;
36use rayon::prelude::*; 37use rayon::prelude::*;
37 38
@@ -41,7 +42,7 @@ use crate::{
41}; 42};
42 43
43salsa::query_group! { 44salsa::query_group! {
44 pub(crate) trait SymbolsDatabase: SyntaxDatabase { 45 pub(crate) trait SymbolsDatabase: hir::db::HirDatabase {
45 fn file_symbols(file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { 46 fn file_symbols(file_id: FileId) -> Cancelable<Arc<SymbolIndex>> {
46 type FileSymbolsQuery; 47 type FileSymbolsQuery;
47 } 48 }
@@ -52,16 +53,26 @@ salsa::query_group! {
52 } 53 }
53} 54}
54 55
55fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { 56fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> {
56 db.check_canceled()?; 57 db.check_canceled()?;
57 let syntax = db.source_file(file_id); 58 let source_file = db.source_file(file_id);
58 Ok(Arc::new(SymbolIndex::for_file(file_id, syntax))) 59 let mut symbols = source_file
60 .syntax()
61 .descendants()
62 .filter_map(to_symbol)
63 .map(move |(name, ptr)| FileSymbol { name, ptr, file_id })
64 .collect::<Vec<_>>();
65
66 for (name, text_range) in hir::source_binder::macro_symbols(db, file_id)? {
67 let node = find_covering_node(source_file.syntax(), text_range);
68 let ptr = LocalSyntaxPtr::new(node);
69 symbols.push(FileSymbol { file_id, name, ptr })
70 }
71
72 Ok(Arc::new(SymbolIndex::new(symbols)))
59} 73}
60 74
61pub(crate) fn world_symbols( 75pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Cancelable<Vec<FileSymbol>> {
62 db: &RootDatabase,
63 query: Query,
64) -> Cancelable<Vec<(FileId, FileSymbol)>> {
65 /// Need to wrap Snapshot to provide `Clone` impl for `map_with` 76 /// Need to wrap Snapshot to provide `Clone` impl for `map_with`
66 struct Snap(salsa::Snapshot<RootDatabase>); 77 struct Snap(salsa::Snapshot<RootDatabase>);
67 impl Clone for Snap { 78 impl Clone for Snap {
@@ -95,7 +106,7 @@ pub(crate) fn world_symbols(
95 106
96#[derive(Default, Debug)] 107#[derive(Default, Debug)]
97pub(crate) struct SymbolIndex { 108pub(crate) struct SymbolIndex {
98 symbols: Vec<(FileId, FileSymbol)>, 109 symbols: Vec<FileSymbol>,
99 map: fst::Map, 110 map: fst::Map,
100} 111}
101 112
@@ -114,6 +125,17 @@ impl Hash for SymbolIndex {
114} 125}
115 126
116impl SymbolIndex { 127impl SymbolIndex {
128 fn new(mut symbols: Vec<FileSymbol>) -> SymbolIndex {
129 fn cmp(s1: &FileSymbol, s2: &FileSymbol) -> Ordering {
130 unicase::Ascii::new(s1.name.as_str()).cmp(&unicase::Ascii::new(s2.name.as_str()))
131 }
132 symbols.par_sort_by(cmp);
133 symbols.dedup_by(|s1, s2| cmp(s1, s2) == Ordering::Equal);
134 let names = symbols.iter().map(|it| it.name.as_str().to_lowercase());
135 let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap();
136 SymbolIndex { symbols, map }
137 }
138
117 pub(crate) fn len(&self) -> usize { 139 pub(crate) fn len(&self) -> usize {
118 self.symbols.len() 140 self.symbols.len()
119 } 141 }
@@ -121,30 +143,21 @@ impl SymbolIndex {
121 pub(crate) fn for_files( 143 pub(crate) fn for_files(
122 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>, 144 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>,
123 ) -> SymbolIndex { 145 ) -> SymbolIndex {
124 let mut symbols = files 146 let symbols = files
125 .flat_map(|(file_id, file)| { 147 .flat_map(|(file_id, file)| {
126 file.syntax() 148 file.syntax()
127 .descendants() 149 .descendants()
128 .filter_map(to_symbol) 150 .filter_map(to_symbol)
129 .map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol))) 151 .map(move |(name, ptr)| FileSymbol { name, ptr, file_id })
130 .collect::<Vec<_>>() 152 .collect::<Vec<_>>()
131 }) 153 })
132 .collect::<Vec<_>>(); 154 .collect::<Vec<_>>();
133 symbols.par_sort_by(|s1, s2| s1.0.cmp(&s2.0)); 155 SymbolIndex::new(symbols)
134 symbols.dedup_by(|s1, s2| s1.0 == s2.0);
135 let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) =
136 symbols.into_iter().unzip();
137 let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap();
138 SymbolIndex { symbols, map }
139 }
140
141 pub(crate) fn for_file(file_id: FileId, file: SourceFileNode) -> SymbolIndex {
142 SymbolIndex::for_files(rayon::iter::once((file_id, file)))
143 } 156 }
144} 157}
145 158
146impl Query { 159impl Query {
147 pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<(FileId, FileSymbol)> { 160 pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> {
148 let mut op = fst::map::OpBuilder::new(); 161 let mut op = fst::map::OpBuilder::new();
149 for file_symbols in indices.iter() { 162 for file_symbols in indices.iter() {
150 let automaton = fst::automaton::Subsequence::new(&self.lowercased); 163 let automaton = fst::automaton::Subsequence::new(&self.lowercased);
@@ -160,14 +173,14 @@ impl Query {
160 let file_symbols = &indices[indexed_value.index]; 173 let file_symbols = &indices[indexed_value.index];
161 let idx = indexed_value.value as usize; 174 let idx = indexed_value.value as usize;
162 175
163 let (file_id, symbol) = &file_symbols.symbols[idx]; 176 let symbol = &file_symbols.symbols[idx];
164 if self.only_types && !is_type(symbol.ptr.kind()) { 177 if self.only_types && !is_type(symbol.ptr.kind()) {
165 continue; 178 continue;
166 } 179 }
167 if self.exact && symbol.name != self.query { 180 if self.exact && symbol.name != self.query {
168 continue; 181 continue;
169 } 182 }
170 res.push((*file_id, symbol.clone())); 183 res.push(symbol.clone());
171 } 184 }
172 } 185 }
173 res 186 res
@@ -185,17 +198,16 @@ fn is_type(kind: SyntaxKind) -> bool {
185/// possible. 198/// possible.
186#[derive(Debug, Clone, PartialEq, Eq, Hash)] 199#[derive(Debug, Clone, PartialEq, Eq, Hash)]
187pub(crate) struct FileSymbol { 200pub(crate) struct FileSymbol {
201 pub(crate) file_id: FileId,
188 pub(crate) name: SmolStr, 202 pub(crate) name: SmolStr,
189 pub(crate) ptr: LocalSyntaxPtr, 203 pub(crate) ptr: LocalSyntaxPtr,
190} 204}
191 205
192fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { 206fn to_symbol(node: SyntaxNodeRef) -> Option<(SmolStr, LocalSyntaxPtr)> {
193 fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<FileSymbol> { 207 fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<(SmolStr, LocalSyntaxPtr)> {
194 let name = node.name()?; 208 let name = node.name()?.text();
195 Some(FileSymbol { 209 let ptr = LocalSyntaxPtr::new(node.syntax());
196 name: name.text(), 210 Some((name, ptr))
197 ptr: LocalSyntaxPtr::new(node.syntax()),
198 })
199 } 211 }
200 visitor() 212 visitor()
201 .visit(decl::<ast::FnDef>) 213 .visit(decl::<ast::FnDef>)
diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs
index ccea4aee3..35e153ca0 100644
--- a/crates/ra_analysis/src/syntax_highlighting.rs
+++ b/crates/ra_analysis/src/syntax_highlighting.rs
@@ -43,6 +43,7 @@ mod tests {
43 " 43 "
44 fn main() { 44 fn main() {
45 ctry!({ let x = 92; x}); 45 ctry!({ let x = 92; x});
46 vec![{ let x = 92; x}];
46 } 47 }
47 ", 48 ",
48 ); 49 );
@@ -53,10 +54,17 @@ mod tests {
53 HighlightedRange { range: [41; 46), tag: "macro" }, 54 HighlightedRange { range: [41; 46), tag: "macro" },
54 HighlightedRange { range: [49; 52), tag: "keyword" }, 55 HighlightedRange { range: [49; 52), tag: "keyword" },
55 HighlightedRange { range: [57; 59), tag: "literal" }, 56 HighlightedRange { range: [57; 59), tag: "literal" },
57 HighlightedRange { range: [82; 86), tag: "macro" },
58 HighlightedRange { range: [89; 92), tag: "keyword" },
59 HighlightedRange { range: [97; 99), tag: "literal" },
56 HighlightedRange { range: [49; 52), tag: "keyword" }, 60 HighlightedRange { range: [49; 52), tag: "keyword" },
57 HighlightedRange { range: [53; 54), tag: "function" }, 61 HighlightedRange { range: [53; 54), tag: "function" },
58 HighlightedRange { range: [57; 59), tag: "literal" }, 62 HighlightedRange { range: [57; 59), tag: "literal" },
59 HighlightedRange { range: [61; 62), tag: "text" }]"#, 63 HighlightedRange { range: [61; 62), tag: "text" },
64 HighlightedRange { range: [89; 92), tag: "keyword" },
65 HighlightedRange { range: [93; 94), tag: "function" },
66 HighlightedRange { range: [97; 99), tag: "literal" },
67 HighlightedRange { range: [101; 102), tag: "text" }]"#,
60 &highlights, 68 &highlights,
61 ) 69 )
62 } 70 }