aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs49
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs12
-rw-r--r--crates/ra_analysis/src/imp.rs27
-rw-r--r--crates/ra_analysis/src/lib.rs8
-rw-r--r--crates/ra_analysis/tests/tests.rs23
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs8
-rw-r--r--crates/ra_lsp_server/src/req.rs2
-rw-r--r--editors/code/src/commands/on_enter.ts6
-rw-r--r--editors/code/src/commands/parent_module.ts11
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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, ModuleItemOwner, NameOwner, AstNode}, 4 ast::{self, ModuleItemOwner, NameOwner},
5 SmolStr, 5 SmolStr,
6}; 6};
7use relative_path::RelativePathBuf; 7use 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
18use super::{ 17use super::{
@@ -23,7 +22,7 @@ use super::{
23#[derive(Clone, Hash, PartialEq, Eq, Debug)] 22#[derive(Clone, Hash, PartialEq, Eq, Debug)]
24pub(crate) enum Submodule { 23pub(crate) enum Submodule {
25 Declaration(SmolStr), 24 Declaration(SmolStr),
26 Definition(SmolStr, SyntaxPtr), 25 Definition(SmolStr, ModuleSource),
27} 26}
28 27
29impl Submodule { 28impl 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
198fn resolve_submodule( 210fn 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
159impl ModuleSource { 157impl 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]
103fn 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
219pub fn handle_parent_module( 219pub 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 {
93pub enum ParentModule {} 93pub enum ParentModule {}
94 94
95impl Request for ParentModule { 95impl 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
9interface OnEnterParams {
10 textDocument: lc.TextDocumentIdentifier;
11 position: lc.Position;
12}
13 9
14export async function handle(event: { text: string }): Promise<boolean> { 10export 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 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2 2
3import { Location, TextDocumentIdentifier } from 'vscode-languageclient'; 3import * as lc from 'vscode-languageclient';
4import { Server } from '../server'; 4import { Server } from '../server';
5 5
6export async function handle() { 6export 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 );