aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/lib.rs')
-rw-r--r--crates/libanalysis/src/lib.rs56
1 files changed, 41 insertions, 15 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 9429f8f55..19b64fece 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -16,7 +16,7 @@ use rayon::prelude::*;
16 16
17use std::{ 17use std::{
18 fmt, 18 fmt,
19 path::Path, 19 path::{Path, PathBuf},
20 sync::{ 20 sync::{
21 Arc, 21 Arc,
22 atomic::{AtomicUsize, Ordering::SeqCst}, 22 atomic::{AtomicUsize, Ordering::SeqCst},
@@ -26,8 +26,9 @@ use std::{
26}; 26};
27 27
28use libsyntax2::{ 28use libsyntax2::{
29 TextUnit, 29 TextUnit, TextRange, SyntaxRoot,
30 ast::{self, AstNode}, 30 ast::{self, AstNode, NameOwner},
31 SyntaxKind::*,
31}; 32};
32use libeditor::{LineIndex, FileSymbol, find_node}; 33use libeditor::{LineIndex, FileSymbol, find_node};
33 34
@@ -119,33 +120,58 @@ impl World {
119 Ok(index.clone()) 120 Ok(index.clone())
120 } 121 }
121 122
122 pub fn world_symbols<'a>(&'a self, mut query: Query) -> impl Iterator<Item=(FileId, &'a FileSymbol)> + 'a { 123 pub fn world_symbols(&self, mut query: Query) -> Vec<(FileId, FileSymbol)> {
123 self.reindex(); 124 self.reindex();
124 self.data.file_map.iter() 125 self.data.file_map.iter()
125 .flat_map(move |(id, data)| { 126 .flat_map(move |(id, data)| {
126 let symbols = data.symbols(); 127 let symbols = data.symbols();
127 query.process(symbols).into_iter().map(move |s| (*id, s)) 128 query.process(symbols).into_iter().map(move |s| (*id, s))
128 }) 129 })
130 .collect()
129 } 131 }
130 132
131 pub fn approximately_resolve_symbol<'a>( 133 pub fn approximately_resolve_symbol(
132 &'a self, 134 &self,
133 id: FileId, 135 id: FileId,
134 offset: TextUnit, 136 offset: TextUnit,
135 ) -> Result<Vec<(FileId, &'a FileSymbol)>> { 137 ) -> Result<Vec<(FileId, FileSymbol)>> {
136 let file = self.file_syntax(id)?; 138 let file = self.file_syntax(id)?;
137 let syntax = file.syntax(); 139 let syntax = file.syntax_ref();
138 let syntax = syntax.as_ref(); 140 if let Some(name_ref) = find_node::<ast::NameRef<_>>(syntax, offset) {
139 let name_ref = find_node::<ast::NameRef<_>>(syntax, offset); 141 return Ok(self.index_resolve(name_ref));
140 let name = match name_ref { 142 }
141 None => return Ok(vec![]), 143 if let Some(name) = find_node::<ast::Name<_>>(syntax, offset) {
142 Some(name_ref) => name_ref.text(), 144 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
143 }; 145 if module.has_semi() {
146 return Ok(self.resolve_module(id, module));
147 }
148 }
149 }
150 Ok(vec![])
151 }
144 152
153 fn index_resolve(&self, name_ref: ast::NameRef<&SyntaxRoot>) -> Vec<(FileId, FileSymbol)> {
154 let name = name_ref.text();
145 let mut query = Query::new(name.to_string()); 155 let mut query = Query::new(name.to_string());
146 query.exact(); 156 query.exact();
147 query.limit(4); 157 query.limit(4);
148 Ok(self.world_symbols(query).collect()) 158 self.world_symbols(query)
159 }
160
161 fn resolve_module(&self, id: FileId, module: ast::Module<&SyntaxRoot>) -> Vec<(FileId, FileSymbol)> {
162 let name = match module.name() {
163 Some(name) => name.text(),
164 None => return Vec::new(),
165 };
166 let id = match self.resolve_relative_path(id, &PathBuf::from(format!("../{}.rs", name))) {
167 Some(id) => id,
168 None => return Vec::new(),
169 };
170 vec![(id, FileSymbol {
171 name: name.clone(),
172 node_range: TextRange::offset_len(0.into(), 0.into()),
173 kind: MODULE,
174 })]
149 } 175 }
150 176
151 fn resolve_relative_path(&self, id: FileId, path: &Path) -> Option<FileId> { 177 fn resolve_relative_path(&self, id: FileId, path: &Path) -> Option<FileId> {