diff options
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/imp.rs | 49 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 12 | ||||
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 27 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ra_analysis/tests/tests.rs | 23 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 8 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 2 | ||||
-rw-r--r-- | editors/code/src/commands/on_enter.ts | 6 | ||||
-rw-r--r-- | editors/code/src/commands/parent_module.ts | 11 |
9 files changed, 99 insertions, 47 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs index 257a323ed..b3b1f1f21 100644 --- a/crates/ra_analysis/src/descriptors/module/imp.rs +++ b/crates/ra_analysis/src/descriptors/module/imp.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | ast::{self, ModuleItemOwner, NameOwner, AstNode}, | 4 | ast::{self, ModuleItemOwner, NameOwner}, |
5 | SmolStr, | 5 | SmolStr, |
6 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | 7 | use relative_path::RelativePathBuf; |
@@ -12,7 +12,6 @@ use crate::{ | |||
12 | descriptors::DescriptorDatabase, | 12 | descriptors::DescriptorDatabase, |
13 | input::{SourceRoot, SourceRootId}, | 13 | input::{SourceRoot, SourceRootId}, |
14 | Cancelable, FileId, FileResolverImp, | 14 | Cancelable, FileId, FileResolverImp, |
15 | syntax_ptr::SyntaxPtr, | ||
16 | }; | 15 | }; |
17 | 16 | ||
18 | use super::{ | 17 | use super::{ |
@@ -23,7 +22,7 @@ use super::{ | |||
23 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | 22 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] |
24 | pub(crate) enum Submodule { | 23 | pub(crate) enum Submodule { |
25 | Declaration(SmolStr), | 24 | Declaration(SmolStr), |
26 | Definition(SmolStr, SyntaxPtr), | 25 | Definition(SmolStr, ModuleSource), |
27 | } | 26 | } |
28 | 27 | ||
29 | impl Submodule { | 28 | impl Submodule { |
@@ -60,7 +59,8 @@ pub(crate) fn submodules( | |||
60 | if m.has_semi() { | 59 | if m.has_semi() { |
61 | Submodule::Declaration(name) | 60 | Submodule::Declaration(name) |
62 | } else { | 61 | } else { |
63 | Submodule::Definition(name, SyntaxPtr::new(file_id, m.syntax())) | 62 | let src = ModuleSource::new_inline(file_id, m); |
63 | Submodule::Definition(name, src) | ||
64 | } | 64 | } |
65 | }) | 65 | }) |
66 | .collect() | 66 | .collect() |
@@ -121,7 +121,8 @@ fn create_module_tree<'a>( | |||
121 | 121 | ||
122 | let source_root = db.source_root(source_root); | 122 | let source_root = db.source_root(source_root); |
123 | for &file_id in source_root.files.iter() { | 123 | for &file_id in source_root.files.iter() { |
124 | if visited.contains(&file_id) { | 124 | let source = ModuleSource::File(file_id); |
125 | if visited.contains(&source) { | ||
125 | continue; // TODO: use explicit crate_roots here | 126 | continue; // TODO: use explicit crate_roots here |
126 | } | 127 | } |
127 | assert!(!roots.contains_key(&file_id)); | 128 | assert!(!roots.contains_key(&file_id)); |
@@ -132,7 +133,7 @@ fn create_module_tree<'a>( | |||
132 | &mut visited, | 133 | &mut visited, |
133 | &mut roots, | 134 | &mut roots, |
134 | None, | 135 | None, |
135 | file_id, | 136 | source, |
136 | )?; | 137 | )?; |
137 | roots.insert(file_id, module_id); | 138 | roots.insert(file_id, module_id); |
138 | } | 139 | } |
@@ -143,18 +144,18 @@ fn build_subtree( | |||
143 | db: &impl DescriptorDatabase, | 144 | db: &impl DescriptorDatabase, |
144 | source_root: &SourceRoot, | 145 | source_root: &SourceRoot, |
145 | tree: &mut ModuleTree, | 146 | tree: &mut ModuleTree, |
146 | visited: &mut FxHashSet<FileId>, | 147 | visited: &mut FxHashSet<ModuleSource>, |
147 | roots: &mut FxHashMap<FileId, ModuleId>, | 148 | roots: &mut FxHashMap<FileId, ModuleId>, |
148 | parent: Option<LinkId>, | 149 | parent: Option<LinkId>, |
149 | file_id: FileId, | 150 | source: ModuleSource, |
150 | ) -> Cancelable<ModuleId> { | 151 | ) -> Cancelable<ModuleId> { |
151 | visited.insert(file_id); | 152 | visited.insert(source); |
152 | let id = tree.push_mod(ModuleData { | 153 | let id = tree.push_mod(ModuleData { |
153 | source: ModuleSource::File(file_id), | 154 | source, |
154 | parent, | 155 | parent, |
155 | children: Vec::new(), | 156 | children: Vec::new(), |
156 | }); | 157 | }); |
157 | for sub in db.submodules(ModuleSource::File(file_id))?.iter() { | 158 | for sub in db.submodules(source)?.iter() { |
158 | let link = tree.push_link(LinkData { | 159 | let link = tree.push_link(LinkData { |
159 | name: sub.name().clone(), | 160 | name: sub.name().clone(), |
160 | owner: id, | 161 | owner: id, |
@@ -165,7 +166,7 @@ fn build_subtree( | |||
165 | let (points_to, problem) = match sub { | 166 | let (points_to, problem) = match sub { |
166 | Submodule::Declaration(name) => { | 167 | Submodule::Declaration(name) => { |
167 | let (points_to, problem) = | 168 | let (points_to, problem) = |
168 | resolve_submodule(file_id, &name, &source_root.file_resolver); | 169 | resolve_submodule(source, &name, &source_root.file_resolver); |
169 | let points_to = points_to | 170 | let points_to = points_to |
170 | .into_iter() | 171 | .into_iter() |
171 | .map(|file_id| match roots.remove(&file_id) { | 172 | .map(|file_id| match roots.remove(&file_id) { |
@@ -180,13 +181,24 @@ fn build_subtree( | |||
180 | visited, | 181 | visited, |
181 | roots, | 182 | roots, |
182 | Some(link), | 183 | Some(link), |
183 | file_id, | 184 | ModuleSource::File(file_id), |
184 | ), | 185 | ), |
185 | }) | 186 | }) |
186 | .collect::<Cancelable<Vec<_>>>()?; | 187 | .collect::<Cancelable<Vec<_>>>()?; |
187 | (points_to, problem) | 188 | (points_to, problem) |
188 | } | 189 | } |
189 | Submodule::Definition(..) => continue, | 190 | Submodule::Definition(_name, submodule_source) => { |
191 | let points_to = build_subtree( | ||
192 | db, | ||
193 | source_root, | ||
194 | tree, | ||
195 | visited, | ||
196 | roots, | ||
197 | Some(link), | ||
198 | *submodule_source, | ||
199 | )?; | ||
200 | (vec![points_to], None) | ||
201 | } | ||
190 | }; | 202 | }; |
191 | 203 | ||
192 | tree.link_mut(link).points_to = points_to; | 204 | tree.link_mut(link).points_to = points_to; |
@@ -196,10 +208,17 @@ fn build_subtree( | |||
196 | } | 208 | } |
197 | 209 | ||
198 | fn resolve_submodule( | 210 | fn resolve_submodule( |
199 | file_id: FileId, | 211 | source: ModuleSource, |
200 | name: &SmolStr, | 212 | name: &SmolStr, |
201 | file_resolver: &FileResolverImp, | 213 | file_resolver: &FileResolverImp, |
202 | ) -> (Vec<FileId>, Option<Problem>) { | 214 | ) -> (Vec<FileId>, Option<Problem>) { |
215 | let file_id = match source { | ||
216 | ModuleSource::File(it) => it, | ||
217 | ModuleSource::Inline(..) => { | ||
218 | // TODO | ||
219 | return (Vec::new(), None); | ||
220 | } | ||
221 | }; | ||
203 | let mod_name = file_resolver.file_stem(file_id); | 222 | let mod_name = file_resolver.file_stem(file_id); |
204 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; | 223 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; |
205 | 224 | ||
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index 8464b0618..3d799ba05 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -142,9 +142,7 @@ impl LinkId { | |||
142 | .1; | 142 | .1; |
143 | ast.into() | 143 | ast.into() |
144 | } | 144 | } |
145 | ModuleSourceNode::Inline(..) => { | 145 | ModuleSourceNode::Inline(it) => it, |
146 | unimplemented!("https://github.com/rust-analyzer/rust-analyzer/issues/181") | ||
147 | } | ||
148 | } | 146 | } |
149 | } | 147 | } |
150 | } | 148 | } |
@@ -157,6 +155,12 @@ struct ModuleData { | |||
157 | } | 155 | } |
158 | 156 | ||
159 | impl ModuleSource { | 157 | impl ModuleSource { |
158 | pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource { | ||
159 | assert!(!module.has_semi()); | ||
160 | let ptr = SyntaxPtr::new(file_id, module.syntax()); | ||
161 | ModuleSource::Inline(ptr) | ||
162 | } | ||
163 | |||
160 | pub(crate) fn as_file(self) -> Option<FileId> { | 164 | pub(crate) fn as_file(self) -> Option<FileId> { |
161 | match self { | 165 | match self { |
162 | ModuleSource::File(f) => Some(f), | 166 | ModuleSource::File(f) => Some(f), |
@@ -164,7 +168,7 @@ impl ModuleSource { | |||
164 | } | 168 | } |
165 | } | 169 | } |
166 | 170 | ||
167 | fn file_id(self) -> FileId { | 171 | pub(crate) fn file_id(self) -> FileId { |
168 | match self { | 172 | match self { |
169 | ModuleSource::File(f) => f, | 173 | ModuleSource::File(f) => f, |
170 | ModuleSource::Inline(ptr) => ptr.file_id(), | 174 | ModuleSource::Inline(ptr) => ptr.file_id(), |
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 823ac9bdd..704648b59 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -220,27 +220,32 @@ impl AnalysisImpl { | |||
220 | let source_root = self.db.file_source_root(file_id); | 220 | let source_root = self.db.file_source_root(file_id); |
221 | self.db.module_tree(source_root) | 221 | self.db.module_tree(source_root) |
222 | } | 222 | } |
223 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 223 | pub fn parent_module( |
224 | &self, | ||
225 | file_id: FileId, | ||
226 | offset: TextUnit, | ||
227 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | ||
224 | let module_tree = self.module_tree(file_id)?; | 228 | let module_tree = self.module_tree(file_id)?; |
229 | let file = self.db.file_syntax(file_id); | ||
230 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), offset) { | ||
231 | Some(m) if !m.has_semi() => ModuleSource::new_inline(file_id, m), | ||
232 | _ => ModuleSource::File(file_id), | ||
233 | }; | ||
225 | 234 | ||
226 | let res = module_tree | 235 | let res = module_tree |
227 | .modules_for_source(ModuleSource::File(file_id)) | 236 | .modules_for_source(module_source) |
228 | .into_iter() | 237 | .into_iter() |
229 | .filter_map(|module_id| { | 238 | .filter_map(|module_id| { |
230 | let link = module_id.parent_link(&module_tree)?; | 239 | let link = module_id.parent_link(&module_tree)?; |
231 | let file_id = match link.owner(&module_tree).source(&module_tree) { | 240 | let file_id = link.owner(&module_tree).source(&module_tree).file_id(); |
232 | ModuleSource::File(file_id) => file_id, | ||
233 | ModuleSource::Inline(..) => { | ||
234 | //TODO: https://github.com/rust-analyzer/rust-analyzer/issues/181 | ||
235 | return None; | ||
236 | } | ||
237 | }; | ||
238 | let decl = link.bind_source(&module_tree, &*self.db); | 241 | let decl = link.bind_source(&module_tree, &*self.db); |
239 | let decl = decl.ast(); | 242 | let decl = decl.ast(); |
240 | 243 | ||
244 | let decl_name = decl.name().unwrap(); | ||
245 | |||
241 | let sym = FileSymbol { | 246 | let sym = FileSymbol { |
242 | name: decl.name().unwrap().text(), | 247 | name: decl_name.text(), |
243 | node_range: decl.syntax().range(), | 248 | node_range: decl_name.syntax().range(), |
244 | kind: MODULE, | 249 | kind: MODULE, |
245 | }; | 250 | }; |
246 | Some((file_id, sym)) | 251 | Some((file_id, sym)) |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 4e4c65f08..fee382151 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -263,8 +263,12 @@ impl Analysis { | |||
263 | ) -> Cancelable<Vec<(FileId, TextRange)>> { | 263 | ) -> Cancelable<Vec<(FileId, TextRange)>> { |
264 | Ok(self.imp.find_all_refs(file_id, offset)) | 264 | Ok(self.imp.find_all_refs(file_id, offset)) |
265 | } | 265 | } |
266 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 266 | pub fn parent_module( |
267 | self.imp.parent_module(file_id) | 267 | &self, |
268 | file_id: FileId, | ||
269 | offset: TextUnit, | ||
270 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | ||
271 | self.imp.parent_module(file_id, offset) | ||
268 | } | 272 | } |
269 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 273 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
270 | self.imp.crate_for(file_id) | 274 | self.imp.crate_for(file_id) |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index c2754c8e4..7f7bb8e6b 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -92,9 +92,28 @@ fn test_resolve_parent_module() { | |||
92 | <|>// empty | 92 | <|>// empty |
93 | ", | 93 | ", |
94 | ); | 94 | ); |
95 | let symbols = analysis.parent_module(pos.file_id).unwrap(); | 95 | let symbols = analysis.parent_module(pos.file_id, pos.offset).unwrap(); |
96 | assert_eq_dbg( | 96 | assert_eq_dbg( |
97 | r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, | 97 | r#"[(FileId(1), FileSymbol { name: "foo", node_range: [4; 7), kind: MODULE })]"#, |
98 | &symbols, | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | #[test] | ||
103 | fn test_resolve_parent_module_for_inline() { | ||
104 | let (analysis, pos) = analysis_and_position( | ||
105 | " | ||
106 | //- /lib.rs | ||
107 | mod foo { | ||
108 | mod bar { | ||
109 | mod baz { <|> } | ||
110 | } | ||
111 | } | ||
112 | ", | ||
113 | ); | ||
114 | let symbols = analysis.parent_module(pos.file_id, pos.offset).unwrap(); | ||
115 | assert_eq_dbg( | ||
116 | r#"[(FileId(1), FileSymbol { name: "bar", node_range: [18; 21), kind: MODULE })]"#, | ||
98 | &symbols, | 117 | &symbols, |
99 | ); | 118 | ); |
100 | } | 119 | } |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index c853ff653..2219a0036 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -218,11 +218,13 @@ pub fn handle_goto_definition( | |||
218 | 218 | ||
219 | pub fn handle_parent_module( | 219 | pub fn handle_parent_module( |
220 | world: ServerWorld, | 220 | world: ServerWorld, |
221 | params: TextDocumentIdentifier, | 221 | params: req::TextDocumentPositionParams, |
222 | ) -> Result<Vec<Location>> { | 222 | ) -> Result<Vec<Location>> { |
223 | let file_id = params.try_conv_with(&world)?; | 223 | let file_id = params.text_document.try_conv_with(&world)?; |
224 | let line_index = world.analysis().file_line_index(file_id); | ||
225 | let offset = params.position.conv_with(&line_index); | ||
224 | let mut res = Vec::new(); | 226 | let mut res = Vec::new(); |
225 | for (file_id, symbol) in world.analysis().parent_module(file_id)? { | 227 | for (file_id, symbol) in world.analysis().parent_module(file_id, offset)? { |
226 | let line_index = world.analysis().file_line_index(file_id); | 228 | let line_index = world.analysis().file_line_index(file_id); |
227 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 229 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; |
228 | res.push(location); | 230 | res.push(location); |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 9d911912d..fcb7e94e1 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -93,7 +93,7 @@ pub struct Decoration { | |||
93 | pub enum ParentModule {} | 93 | pub enum ParentModule {} |
94 | 94 | ||
95 | impl Request for ParentModule { | 95 | impl Request for ParentModule { |
96 | type Params = TextDocumentIdentifier; | 96 | type Params = TextDocumentPositionParams; |
97 | type Result = Vec<Location>; | 97 | type Result = Vec<Location>; |
98 | const METHOD: &'static str = "m/parentModule"; | 98 | const METHOD: &'static str = "m/parentModule"; |
99 | } | 99 | } |
diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts index fe6aca63d..64401b684 100644 --- a/editors/code/src/commands/on_enter.ts +++ b/editors/code/src/commands/on_enter.ts | |||
@@ -6,10 +6,6 @@ import { | |||
6 | SourceChange | 6 | SourceChange |
7 | } from './apply_source_change'; | 7 | } from './apply_source_change'; |
8 | 8 | ||
9 | interface OnEnterParams { | ||
10 | textDocument: lc.TextDocumentIdentifier; | ||
11 | position: lc.Position; | ||
12 | } | ||
13 | 9 | ||
14 | export async function handle(event: { text: string }): Promise<boolean> { | 10 | export async function handle(event: { text: string }): Promise<boolean> { |
15 | const editor = vscode.window.activeTextEditor; | 11 | const editor = vscode.window.activeTextEditor; |
@@ -20,7 +16,7 @@ export async function handle(event: { text: string }): Promise<boolean> { | |||
20 | ) { | 16 | ) { |
21 | return false; | 17 | return false; |
22 | } | 18 | } |
23 | const request: OnEnterParams = { | 19 | const request: lc.TextDocumentPositionParams = { |
24 | textDocument: { uri: editor.document.uri.toString() }, | 20 | textDocument: { uri: editor.document.uri.toString() }, |
25 | position: Server.client.code2ProtocolConverter.asPosition( | 21 | position: Server.client.code2ProtocolConverter.asPosition( |
26 | editor.selection.active | 22 | editor.selection.active |
diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts index 4bb92eb96..806c3d34c 100644 --- a/editors/code/src/commands/parent_module.ts +++ b/editors/code/src/commands/parent_module.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | 2 | ||
3 | import { Location, TextDocumentIdentifier } from 'vscode-languageclient'; | 3 | import * as lc from 'vscode-languageclient'; |
4 | import { Server } from '../server'; | 4 | import { Server } from '../server'; |
5 | 5 | ||
6 | export async function handle() { | 6 | export async function handle() { |
@@ -8,10 +8,13 @@ export async function handle() { | |||
8 | if (editor == null || editor.document.languageId !== 'rust') { | 8 | if (editor == null || editor.document.languageId !== 'rust') { |
9 | return; | 9 | return; |
10 | } | 10 | } |
11 | const request: TextDocumentIdentifier = { | 11 | const request: lc.TextDocumentPositionParams = { |
12 | uri: editor.document.uri.toString() | 12 | textDocument: { uri: editor.document.uri.toString() }, |
13 | position: Server.client.code2ProtocolConverter.asPosition( | ||
14 | editor.selection.active | ||
15 | ) | ||
13 | }; | 16 | }; |
14 | const response = await Server.client.sendRequest<Location[]>( | 17 | const response = await Server.client.sendRequest<lc.Location[]>( |
15 | 'm/parentModule', | 18 | 'm/parentModule', |
16 | request | 19 | request |
17 | ); | 20 | ); |