aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-17 13:37:17 +0100
committerAleksey Kladov <[email protected]>2018-08-17 13:37:17 +0100
commit081c16c77642a5c86ed72c5fbd11deccc2edd5d5 (patch)
tree90ddf4f92954fcb00f4c20a46968932c5f0bbdea
parent55e87e0b742b46d40b1a5ef1598804e48e45f0e0 (diff)
initial mod resolve
-rw-r--r--crates/libanalysis/src/lib.rs56
-rw-r--r--crates/libanalysis/src/symbol_index.rs8
-rw-r--r--crates/libeditor/src/symbols.rs4
-rw-r--r--crates/libsyntax2/src/ast/mod.rs9
-rw-r--r--crates/libsyntax2/src/yellow/syntax.rs10
-rw-r--r--crates/server/src/path_map.rs47
6 files changed, 111 insertions, 23 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> {
diff --git a/crates/libanalysis/src/symbol_index.rs b/crates/libanalysis/src/symbol_index.rs
index 35141cfdc..3c3252956 100644
--- a/crates/libanalysis/src/symbol_index.rs
+++ b/crates/libanalysis/src/symbol_index.rs
@@ -62,10 +62,10 @@ impl Query {
62 self.limit = limit 62 self.limit = limit
63 } 63 }
64 64
65 pub(crate) fn process<'a>( 65 pub(crate) fn process(
66 &mut self, 66 &mut self,
67 file: &'a FileSymbols, 67 file: &FileSymbols,
68 ) -> Vec<&'a FileSymbol> { 68 ) -> Vec<FileSymbol> {
69 fn is_type(kind: SyntaxKind) -> bool { 69 fn is_type(kind: SyntaxKind) -> bool {
70 match kind { 70 match kind {
71 STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_DEF => true, 71 STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_DEF => true,
@@ -87,7 +87,7 @@ impl Query {
87 if self.exact && symbol.name != self.query { 87 if self.exact && symbol.name != self.query {
88 continue; 88 continue;
89 } 89 }
90 res.push(symbol); 90 res.push(symbol.clone());
91 self.limit -= 1; 91 self.limit -= 1;
92 } 92 }
93 res 93 res
diff --git a/crates/libeditor/src/symbols.rs b/crates/libeditor/src/symbols.rs
index 2585d9579..ce870430e 100644
--- a/crates/libeditor/src/symbols.rs
+++ b/crates/libeditor/src/symbols.rs
@@ -9,7 +9,7 @@ use libsyntax2::{
9}; 9};
10use TextRange; 10use TextRange;
11 11
12#[derive(Debug)] 12#[derive(Debug, Clone)]
13pub struct StructureNode { 13pub struct StructureNode {
14 pub parent: Option<usize>, 14 pub parent: Option<usize>,
15 pub label: String, 15 pub label: String,
@@ -18,7 +18,7 @@ pub struct StructureNode {
18 pub kind: SyntaxKind, 18 pub kind: SyntaxKind,
19} 19}
20 20
21#[derive(Debug)] 21#[derive(Debug, Clone)]
22pub struct FileSymbol { 22pub struct FileSymbol {
23 pub name: SmolStr, 23 pub name: SmolStr,
24 pub node_range: TextRange, 24 pub node_range: TextRange,
diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs
index d53b12ab8..9b9200f99 100644
--- a/crates/libsyntax2/src/ast/mod.rs
+++ b/crates/libsyntax2/src/ast/mod.rs
@@ -118,3 +118,12 @@ impl <R: TreeRoot> ImplItem<R> {
118 (first, second) 118 (first, second)
119 } 119 }
120} 120}
121
122impl <R: TreeRoot> Module<R> {
123 pub fn has_semi(&self) -> bool {
124 match self.syntax_ref().last_child() {
125 None => false,
126 Some(node) => node.kind() == SEMI,
127 }
128 }
129}
diff --git a/crates/libsyntax2/src/yellow/syntax.rs b/crates/libsyntax2/src/yellow/syntax.rs
index b264e008a..bb390751a 100644
--- a/crates/libsyntax2/src/yellow/syntax.rs
+++ b/crates/libsyntax2/src/yellow/syntax.rs
@@ -89,7 +89,15 @@ impl<R: TreeRoot> SyntaxNode<R> {
89 } 89 }
90 90
91 pub fn first_child(&self) -> Option<SyntaxNode<R>> { 91 pub fn first_child(&self) -> Option<SyntaxNode<R>> {
92 self.children().next() 92 let red = self.red().get_child(0)?;
93 Some(SyntaxNode { root: self.root.clone(), red })
94 }
95
96 pub fn last_child(&self) -> Option<SyntaxNode<R>> {
97 let n = self.red().n_children();
98 let n = n.checked_sub(1)?;
99 let red = self.red().get_child(n)?;
100 Some(SyntaxNode { root: self.root.clone(), red })
93 } 101 }
94 102
95 pub fn next_sibling(&self) -> Option<SyntaxNode<R>> { 103 pub fn next_sibling(&self) -> Option<SyntaxNode<R>> {
diff --git a/crates/server/src/path_map.rs b/crates/server/src/path_map.rs
index e198e165d..d2b811a3b 100644
--- a/crates/server/src/path_map.rs
+++ b/crates/server/src/path_map.rs
@@ -1,4 +1,4 @@
1use std::path::{PathBuf, Path}; 1use std::path::{PathBuf, Path, Component};
2use im; 2use im;
3use libanalysis::{FileId}; 3use libanalysis::{FileId};
4 4
@@ -36,6 +36,7 @@ impl PathMap {
36 36
37 pub fn resolve(&self, id: FileId, relpath: &Path) -> Option<FileId> { 37 pub fn resolve(&self, id: FileId, relpath: &Path) -> Option<FileId> {
38 let path = self.get_path(id).join(relpath); 38 let path = self.get_path(id).join(relpath);
39 let path = normalize(&path);
39 self.get_id(&path) 40 self.get_id(&path)
40 } 41 }
41 42
@@ -50,3 +51,47 @@ impl PathMap {
50 id 51 id
51 } 52 }
52} 53}
54
55fn normalize(path: &Path) -> PathBuf {
56 let mut components = path.components().peekable();
57 let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
58 components.next();
59 PathBuf::from(c.as_os_str())
60 } else {
61 PathBuf::new()
62 };
63
64 for component in components {
65 match component {
66 Component::Prefix(..) => unreachable!(),
67 Component::RootDir => {
68 ret.push(component.as_os_str());
69 }
70 Component::CurDir => {}
71 Component::ParentDir => {
72 ret.pop();
73 }
74 Component::Normal(c) => {
75 ret.push(c);
76 }
77 }
78 }
79 ret
80}
81
82#[cfg(test)]
83mod test {
84 use super::*;
85
86 #[test]
87 fn test_resolve() {
88 let mut m = PathMap::new();
89 let id1 = m.get_or_insert(PathBuf::from("/foo"));
90 let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs"));
91 assert_eq!(
92 m.resolve(id1, &PathBuf::from("bar.rs")),
93 Some(id2),
94 )
95 }
96}
97