diff options
35 files changed, 422 insertions, 366 deletions
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs index 286b6c376..6bd1233f9 100644 --- a/crates/ra_analysis/src/completion.rs +++ b/crates/ra_analysis/src/completion.rs | |||
@@ -1,22 +1,22 @@ | |||
1 | use rustc_hash::{FxHashMap, FxHashSet}; | 1 | use ra_editor::find_node_at_offset; |
2 | use ra_editor::{find_node_at_offset}; | ||
3 | use ra_syntax::{ | 2 | use ra_syntax::{ |
4 | AtomEdit, File, TextUnit, AstNode, SyntaxNodeRef, | ||
5 | algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, | 3 | algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, |
6 | ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, | 4 | ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, |
5 | AstNode, AtomEdit, File, | ||
7 | SyntaxKind::*, | 6 | SyntaxKind::*, |
7 | SyntaxNodeRef, TextUnit, | ||
8 | }; | 8 | }; |
9 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
9 | 10 | ||
10 | use crate::{ | 11 | use crate::{ |
11 | FileId, Cancelable, | ||
12 | input::FilesDatabase, | ||
13 | db::{self, SyntaxDatabase}, | 12 | db::{self, SyntaxDatabase}, |
14 | descriptors::DescriptorDatabase, | ||
15 | descriptors::function::FnScopes, | 13 | descriptors::function::FnScopes, |
16 | descriptors::module::{ModuleTree, ModuleId, ModuleScope}, | 14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree}, |
15 | descriptors::DescriptorDatabase, | ||
16 | input::FilesDatabase, | ||
17 | Cancelable, FileId, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | |||
20 | #[derive(Debug)] | 20 | #[derive(Debug)] |
21 | pub struct CompletionItem { | 21 | pub struct CompletionItem { |
22 | /// What user sees in pop-up | 22 | /// What user sees in pop-up |
@@ -27,7 +27,11 @@ pub struct CompletionItem { | |||
27 | pub snippet: Option<String>, | 27 | pub snippet: Option<String>, |
28 | } | 28 | } |
29 | 29 | ||
30 | pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { | 30 | pub(crate) fn resolve_based_completion( |
31 | db: &db::RootDatabase, | ||
32 | file_id: FileId, | ||
33 | offset: TextUnit, | ||
34 | ) -> Cancelable<Option<Vec<CompletionItem>>> { | ||
31 | let source_root_id = db.file_source_root(file_id); | 35 | let source_root_id = db.file_source_root(file_id); |
32 | let file = db.file_syntax(file_id); | 36 | let file = db.file_syntax(file_id); |
33 | let module_tree = db.module_tree(source_root_id)?; | 37 | let module_tree = db.module_tree(source_root_id)?; |
@@ -56,9 +60,12 @@ pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, o | |||
56 | Ok(Some(res)) | 60 | Ok(Some(res)) |
57 | } | 61 | } |
58 | 62 | ||
59 | 63 | pub(crate) fn find_target_module( | |
60 | 64 | module_tree: &ModuleTree, | |
61 | pub(crate) fn find_target_module(module_tree: &ModuleTree, module_id: ModuleId, file: &File, offset: TextUnit) -> Option<ModuleId> { | 65 | module_id: ModuleId, |
66 | file: &File, | ||
67 | offset: TextUnit, | ||
68 | ) -> Option<ModuleId> { | ||
62 | let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?; | 69 | let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?; |
63 | let mut crate_path = crate_path(name_ref)?; | 70 | let mut crate_path = crate_path(name_ref)?; |
64 | 71 | ||
@@ -71,8 +78,10 @@ pub(crate) fn find_target_module(module_tree: &ModuleTree, module_id: ModuleId, | |||
71 | } | 78 | } |
72 | 79 | ||
73 | fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> { | 80 | fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> { |
74 | let mut path = name_ref.syntax() | 81 | let mut path = name_ref |
75 | .parent().and_then(ast::PathSegment::cast)? | 82 | .syntax() |
83 | .parent() | ||
84 | .and_then(ast::PathSegment::cast)? | ||
76 | .parent_path(); | 85 | .parent_path(); |
77 | let mut res = Vec::new(); | 86 | let mut res = Vec::new(); |
78 | loop { | 87 | loop { |
@@ -80,8 +89,7 @@ fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> { | |||
80 | match segment.kind()? { | 89 | match segment.kind()? { |
81 | ast::PathSegmentKind::Name(name) => res.push(name), | 90 | ast::PathSegmentKind::Name(name) => res.push(name), |
82 | ast::PathSegmentKind::CrateKw => break, | 91 | ast::PathSegmentKind::CrateKw => break, |
83 | ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => | 92 | ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None, |
84 | return None, | ||
85 | } | 93 | } |
86 | path = path.qualifier()?; | 94 | path = path.qualifier()?; |
87 | } | 95 | } |
@@ -89,7 +97,6 @@ fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> { | |||
89 | Some(res) | 97 | Some(res) |
90 | } | 98 | } |
91 | 99 | ||
92 | |||
93 | pub(crate) fn scope_completion( | 100 | pub(crate) fn scope_completion( |
94 | db: &db::RootDatabase, | 101 | db: &db::RootDatabase, |
95 | file_id: FileId, | 102 | file_id: FileId, |
@@ -158,11 +165,7 @@ fn complete_module_items( | |||
158 | ); | 165 | ); |
159 | } | 166 | } |
160 | 167 | ||
161 | fn complete_name_ref( | 168 | fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) { |
162 | file: &File, | ||
163 | name_ref: ast::NameRef, | ||
164 | acc: &mut Vec<CompletionItem>, | ||
165 | ) { | ||
166 | if !is_node::<ast::Path>(name_ref.syntax()) { | 169 | if !is_node::<ast::Path>(name_ref.syntax()) { |
167 | return; | 170 | return; |
168 | } | 171 | } |
@@ -273,7 +276,11 @@ fn is_in_loop_body(name_ref: ast::NameRef) -> bool { | |||
273 | .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body) | 276 | .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body) |
274 | .accept(node); | 277 | .accept(node); |
275 | if let Some(Some(body)) = loop_body { | 278 | if let Some(Some(body)) = loop_body { |
276 | if name_ref.syntax().range().is_subrange(&body.syntax().range()) { | 279 | if name_ref |
280 | .syntax() | ||
281 | .range() | ||
282 | .is_subrange(&body.syntax().range()) | ||
283 | { | ||
277 | return true; | 284 | return true; |
278 | } | 285 | } |
279 | } | 286 | } |
@@ -368,9 +375,9 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi | |||
368 | 375 | ||
369 | #[cfg(test)] | 376 | #[cfg(test)] |
370 | mod tests { | 377 | mod tests { |
371 | use test_utils::{assert_eq_dbg}; | 378 | use test_utils::assert_eq_dbg; |
372 | 379 | ||
373 | use crate::mock_analysis::{single_file_with_position}; | 380 | use crate::mock_analysis::single_file_with_position; |
374 | 381 | ||
375 | use super::*; | 382 | use super::*; |
376 | 383 | ||
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index f1ace3d5a..9ab273ad7 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -1,6 +1,4 @@ | |||
1 | use std::{ | 1 | use std::sync::Arc; |
2 | sync::Arc, | ||
3 | }; | ||
4 | 2 | ||
5 | use ra_editor::LineIndex; | 3 | use ra_editor::LineIndex; |
6 | use ra_syntax::File; | 4 | use ra_syntax::File; |
@@ -8,14 +6,13 @@ use salsa; | |||
8 | 6 | ||
9 | use crate::{ | 7 | use crate::{ |
10 | db, | 8 | db, |
11 | Cancelable, Canceled, | ||
12 | descriptors::{ | 9 | descriptors::{ |
13 | DescriptorDatabase, SubmodulesQuery, ModuleTreeQuery, ModuleScopeQuery, | 10 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, |
14 | FnSyntaxQuery, FnScopesQuery | 11 | SubmodulesQuery, |
15 | }, | 12 | }, |
16 | symbol_index::SymbolIndex, | 13 | symbol_index::SymbolIndex, |
17 | syntax_ptr::{SyntaxPtrDatabase, ResolveSyntaxPtrQuery}, | 14 | syntax_ptr::{ResolveSyntaxPtrQuery, SyntaxPtrDatabase}, |
18 | FileId, | 15 | Cancelable, Canceled, FileId, |
19 | }; | 16 | }; |
20 | 17 | ||
21 | #[derive(Default, Debug)] | 18 | #[derive(Default, Debug)] |
diff --git a/crates/ra_analysis/src/descriptors/function/imp.rs b/crates/ra_analysis/src/descriptors/function/imp.rs index 0a006f733..11fffeefc 100644 --- a/crates/ra_analysis/src/descriptors/function/imp.rs +++ b/crates/ra_analysis/src/descriptors/function/imp.rs | |||
@@ -1,14 +1,10 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::ast::{AstNode, FnDef, FnDefNode}; |
4 | ast::{AstNode, FnDef, FnDefNode}, | ||
5 | }; | ||
6 | 4 | ||
7 | use crate::{ | 5 | use crate::descriptors::{ |
8 | descriptors::{ | 6 | function::{FnId, FnScopes}, |
9 | DescriptorDatabase, | 7 | DescriptorDatabase, |
10 | function::{FnId, FnScopes}, | ||
11 | }, | ||
12 | }; | 8 | }; |
13 | 9 | ||
14 | /// Resolve `FnId` to the corresponding `SyntaxNode` | 10 | /// Resolve `FnId` to the corresponding `SyntaxNode` |
diff --git a/crates/ra_analysis/src/descriptors/function/mod.rs b/crates/ra_analysis/src/descriptors/function/mod.rs index ae40f3e8f..d5db28a64 100644 --- a/crates/ra_analysis/src/descriptors/function/mod.rs +++ b/crates/ra_analysis/src/descriptors/function/mod.rs | |||
@@ -1,20 +1,16 @@ | |||
1 | pub(super) mod imp; | 1 | pub(super) mod imp; |
2 | mod scope; | 2 | mod scope; |
3 | 3 | ||
4 | use std::cmp::{min, max}; | 4 | use std::cmp::{max, min}; |
5 | 5 | ||
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | ast::{self, AstNode, DocCommentsOwner, NameOwner}, | 7 | ast::{self, AstNode, DocCommentsOwner, NameOwner}, |
8 | TextRange, TextUnit | 8 | TextRange, TextUnit, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{syntax_ptr::SyntaxPtr, FileId}; |
12 | FileId, | ||
13 | syntax_ptr::SyntaxPtr | ||
14 | }; | ||
15 | |||
16 | pub(crate) use self::scope::{FnScopes, resolve_local_name}; | ||
17 | 12 | ||
13 | pub(crate) use self::scope::{resolve_local_name, FnScopes}; | ||
18 | 14 | ||
19 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 15 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
20 | pub(crate) struct FnId(SyntaxPtr); | 16 | pub(crate) struct FnId(SyntaxPtr); |
@@ -26,14 +22,13 @@ impl FnId { | |||
26 | } | 22 | } |
27 | } | 23 | } |
28 | 24 | ||
29 | |||
30 | #[derive(Debug, Clone)] | 25 | #[derive(Debug, Clone)] |
31 | pub struct FnDescriptor { | 26 | pub struct FnDescriptor { |
32 | pub name: String, | 27 | pub name: String, |
33 | pub label: String, | 28 | pub label: String, |
34 | pub ret_type: Option<String>, | 29 | pub ret_type: Option<String>, |
35 | pub params: Vec<String>, | 30 | pub params: Vec<String>, |
36 | pub doc: Option<String> | 31 | pub doc: Option<String>, |
37 | } | 32 | } |
38 | 33 | ||
39 | impl FnDescriptor { | 34 | impl FnDescriptor { |
@@ -57,7 +52,9 @@ impl FnDescriptor { | |||
57 | }; | 52 | }; |
58 | 53 | ||
59 | if let Some((comment_range, docs)) = FnDescriptor::extract_doc_comments(node) { | 54 | if let Some((comment_range, docs)) = FnDescriptor::extract_doc_comments(node) { |
60 | let comment_range = comment_range.checked_sub(node.syntax().range().start()).unwrap(); | 55 | let comment_range = comment_range |
56 | .checked_sub(node.syntax().range().start()) | ||
57 | .unwrap(); | ||
61 | let start = comment_range.start().to_usize(); | 58 | let start = comment_range.start().to_usize(); |
62 | let end = comment_range.end().to_usize(); | 59 | let end = comment_range.end().to_usize(); |
63 | 60 | ||
@@ -94,7 +91,7 @@ impl FnDescriptor { | |||
94 | ret_type, | 91 | ret_type, |
95 | params, | 92 | params, |
96 | label: label.trim().to_owned(), | 93 | label: label.trim().to_owned(), |
97 | doc | 94 | doc, |
98 | }) | 95 | }) |
99 | } | 96 | } |
100 | 97 | ||
@@ -105,10 +102,13 @@ impl FnDescriptor { | |||
105 | 102 | ||
106 | let comment_text = node.doc_comment_text(); | 103 | let comment_text = node.doc_comment_text(); |
107 | 104 | ||
108 | let (begin, end) = node.doc_comments() | 105 | let (begin, end) = node |
106 | .doc_comments() | ||
109 | .map(|comment| comment.syntax().range()) | 107 | .map(|comment| comment.syntax().range()) |
110 | .map(|range| (range.start().to_usize(), range.end().to_usize())) | 108 | .map(|range| (range.start().to_usize(), range.end().to_usize())) |
111 | .fold((std::usize::MAX, std::usize::MIN), |acc, range| (min(acc.0, range.0), max(acc.1, range.1))); | 109 | .fold((std::usize::MAX, std::usize::MIN), |acc, range| { |
110 | (min(acc.0, range.0), max(acc.1, range.1)) | ||
111 | }); | ||
112 | 112 | ||
113 | let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end)); | 113 | let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end)); |
114 | 114 | ||
@@ -134,4 +134,3 @@ impl FnDescriptor { | |||
134 | res | 134 | res |
135 | } | 135 | } |
136 | } | 136 | } |
137 | |||
diff --git a/crates/ra_analysis/src/descriptors/function/scope.rs b/crates/ra_analysis/src/descriptors/function/scope.rs index d9929414c..62b46ffba 100644 --- a/crates/ra_analysis/src/descriptors/function/scope.rs +++ b/crates/ra_analysis/src/descriptors/function/scope.rs | |||
@@ -51,9 +51,7 @@ impl FnScopes { | |||
51 | &self.get(scope).entries | 51 | &self.get(scope).entries |
52 | } | 52 | } |
53 | pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a { | 53 | pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a { |
54 | generate(self.scope_for(node), move |&scope| { | 54 | generate(self.scope_for(node), move |&scope| self.get(scope).parent) |
55 | self.get(scope).parent | ||
56 | }) | ||
57 | } | 55 | } |
58 | fn root_scope(&mut self) -> ScopeId { | 56 | fn root_scope(&mut self) -> ScopeId { |
59 | let res = ScopeId(self.scopes.len() as u32); | 57 | let res = ScopeId(self.scopes.len() as u32); |
@@ -273,13 +271,12 @@ pub fn resolve_local_name<'a>( | |||
273 | 271 | ||
274 | #[cfg(test)] | 272 | #[cfg(test)] |
275 | mod tests { | 273 | mod tests { |
274 | use ra_editor::find_node_at_offset; | ||
276 | use ra_syntax::File; | 275 | use ra_syntax::File; |
277 | use test_utils::extract_offset; | 276 | use test_utils::extract_offset; |
278 | use ra_editor::{find_node_at_offset}; | ||
279 | 277 | ||
280 | use super::*; | 278 | use super::*; |
281 | 279 | ||
282 | |||
283 | fn do_check(code: &str, expected: &[&str]) { | 280 | fn do_check(code: &str, expected: &[&str]) { |
284 | let (off, code) = extract_offset(code); | 281 | let (off, code) = extract_offset(code); |
285 | let code = { | 282 | let code = { |
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index e27f8314a..c28764336 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs | |||
@@ -1,24 +1,22 @@ | |||
1 | pub(crate) mod module; | ||
2 | pub(crate) mod function; | 1 | pub(crate) mod function; |
2 | pub(crate) mod module; | ||
3 | 3 | ||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | SmolStr, | ||
8 | ast::{self, AstNode, FnDefNode}, | 7 | ast::{self, AstNode, FnDefNode}, |
9 | TextRange | 8 | SmolStr, TextRange, |
10 | }; | 9 | }; |
11 | 10 | ||
12 | use crate::{ | 11 | use crate::{ |
13 | FileId, Cancelable, | ||
14 | db::SyntaxDatabase, | 12 | db::SyntaxDatabase, |
15 | descriptors::module::{ModuleTree, ModuleId, ModuleScope}, | 13 | descriptors::function::{resolve_local_name, FnId, FnScopes}, |
16 | descriptors::function::{FnId, FnScopes, resolve_local_name}, | 14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree}, |
17 | input::SourceRootId, | 15 | input::SourceRootId, |
18 | syntax_ptr::{SyntaxPtrDatabase, LocalSyntaxPtr}, | 16 | syntax_ptr::{LocalSyntaxPtr, SyntaxPtrDatabase}, |
17 | Cancelable, FileId, | ||
19 | }; | 18 | }; |
20 | 19 | ||
21 | |||
22 | salsa::query_group! { | 20 | salsa::query_group! { |
23 | pub(crate) trait DescriptorDatabase: SyntaxDatabase + SyntaxPtrDatabase { | 21 | pub(crate) trait DescriptorDatabase: SyntaxDatabase + SyntaxPtrDatabase { |
24 | fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { | 22 | fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { |
@@ -49,23 +47,20 @@ salsa::query_group! { | |||
49 | #[derive(Debug)] | 47 | #[derive(Debug)] |
50 | pub struct ReferenceDescriptor { | 48 | pub struct ReferenceDescriptor { |
51 | pub range: TextRange, | 49 | pub range: TextRange, |
52 | pub name: String | 50 | pub name: String, |
53 | } | 51 | } |
54 | 52 | ||
55 | #[derive(Debug)] | 53 | #[derive(Debug)] |
56 | pub struct DeclarationDescriptor<'a> { | 54 | pub struct DeclarationDescriptor<'a> { |
57 | pat: ast::BindPat<'a>, | 55 | pat: ast::BindPat<'a>, |
58 | pub range: TextRange | 56 | pub range: TextRange, |
59 | } | 57 | } |
60 | 58 | ||
61 | impl<'a> DeclarationDescriptor<'a> { | 59 | impl<'a> DeclarationDescriptor<'a> { |
62 | pub fn new(pat: ast::BindPat) -> DeclarationDescriptor { | 60 | pub fn new(pat: ast::BindPat) -> DeclarationDescriptor { |
63 | let range = pat.syntax().range(); | 61 | let range = pat.syntax().range(); |
64 | 62 | ||
65 | DeclarationDescriptor { | 63 | DeclarationDescriptor { pat, range } |
66 | pat, | ||
67 | range | ||
68 | } | ||
69 | } | 64 | } |
70 | 65 | ||
71 | pub fn find_all_refs(&self) -> Vec<ReferenceDescriptor> { | 66 | pub fn find_all_refs(&self) -> Vec<ReferenceDescriptor> { |
@@ -73,22 +68,22 @@ impl<'a> DeclarationDescriptor<'a> { | |||
73 | 68 | ||
74 | let fn_def = match self.pat.syntax().ancestors().find_map(ast::FnDef::cast) { | 69 | let fn_def = match self.pat.syntax().ancestors().find_map(ast::FnDef::cast) { |
75 | Some(def) => def, | 70 | Some(def) => def, |
76 | None => return Default::default() | 71 | None => return Default::default(), |
77 | }; | 72 | }; |
78 | 73 | ||
79 | let fn_scopes = FnScopes::new(fn_def); | 74 | let fn_scopes = FnScopes::new(fn_def); |
80 | 75 | ||
81 | let refs : Vec<_> = fn_def.syntax().descendants() | 76 | let refs: Vec<_> = fn_def |
77 | .syntax() | ||
78 | .descendants() | ||
82 | .filter_map(ast::NameRef::cast) | 79 | .filter_map(ast::NameRef::cast) |
83 | .filter(|name_ref| { | 80 | .filter(|name_ref| match resolve_local_name(*name_ref, &fn_scopes) { |
84 | match resolve_local_name(*name_ref, &fn_scopes) { | 81 | None => false, |
85 | None => false, | 82 | Some(entry) => entry.ptr() == name_ptr, |
86 | Some(entry) => entry.ptr() == name_ptr, | ||
87 | } | ||
88 | }) | 83 | }) |
89 | .map(|name_ref| ReferenceDescriptor { | 84 | .map(|name_ref| ReferenceDescriptor { |
90 | name: name_ref.syntax().text().to_string(), | 85 | name: name_ref.syntax().text().to_string(), |
91 | range : name_ref.syntax().range(), | 86 | range: name_ref.syntax().range(), |
92 | }) | 87 | }) |
93 | .collect(); | 88 | .collect(); |
94 | 89 | ||
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs index dae3a356d..1c102f4e5 100644 --- a/crates/ra_analysis/src/descriptors/module/imp.rs +++ b/crates/ra_analysis/src/descriptors/module/imp.rs | |||
@@ -1,24 +1,25 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use relative_path::RelativePathBuf; | ||
4 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
5 | use ra_syntax::{ | 3 | use ra_syntax::{ |
6 | SmolStr, | ||
7 | ast::{self, NameOwner}, | 4 | ast::{self, NameOwner}, |
5 | SmolStr, | ||
8 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | ||
8 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | FileId, Cancelable, FileResolverImp, db, | 11 | db, |
12 | input::{SourceRoot, SourceRootId}, | ||
13 | descriptors::DescriptorDatabase, | 12 | descriptors::DescriptorDatabase, |
13 | input::{SourceRoot, SourceRootId}, | ||
14 | Cancelable, FileId, FileResolverImp, | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | use super::{ | 17 | use super::{LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleTree, Problem}; |
17 | ModuleData, ModuleTree, ModuleId, LinkId, LinkData, Problem, ModuleScope | ||
18 | }; | ||
19 | |||
20 | 18 | ||
21 | pub(crate) fn submodules(db: &impl DescriptorDatabase, file_id: FileId) -> Cancelable<Arc<Vec<SmolStr>>> { | 19 | pub(crate) fn submodules( |
20 | db: &impl DescriptorDatabase, | ||
21 | file_id: FileId, | ||
22 | ) -> Cancelable<Arc<Vec<SmolStr>>> { | ||
22 | db::check_canceled(db)?; | 23 | db::check_canceled(db)?; |
23 | let file = db.file_syntax(file_id); | 24 | let file = db.file_syntax(file_id); |
24 | let root = file.ast(); | 25 | let root = file.ast(); |
@@ -57,13 +58,11 @@ pub(crate) fn module_tree( | |||
57 | Ok(Arc::new(res)) | 58 | Ok(Arc::new(res)) |
58 | } | 59 | } |
59 | 60 | ||
60 | |||
61 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | 61 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] |
62 | pub struct Submodule { | 62 | pub struct Submodule { |
63 | pub name: SmolStr, | 63 | pub name: SmolStr, |
64 | } | 64 | } |
65 | 65 | ||
66 | |||
67 | fn create_module_tree<'a>( | 66 | fn create_module_tree<'a>( |
68 | db: &impl DescriptorDatabase, | 67 | db: &impl DescriptorDatabase, |
69 | source_root: SourceRootId, | 68 | source_root: SourceRootId, |
@@ -82,7 +81,15 @@ fn create_module_tree<'a>( | |||
82 | continue; // TODO: use explicit crate_roots here | 81 | continue; // TODO: use explicit crate_roots here |
83 | } | 82 | } |
84 | assert!(!roots.contains_key(&file_id)); | 83 | assert!(!roots.contains_key(&file_id)); |
85 | let module_id = build_subtree(db, &source_root, &mut tree, &mut visited, &mut roots, None, file_id)?; | 84 | let module_id = build_subtree( |
85 | db, | ||
86 | &source_root, | ||
87 | &mut tree, | ||
88 | &mut visited, | ||
89 | &mut roots, | ||
90 | None, | ||
91 | file_id, | ||
92 | )?; | ||
86 | roots.insert(file_id, module_id); | 93 | roots.insert(file_id, module_id); |
87 | } | 94 | } |
88 | Ok(tree) | 95 | Ok(tree) |
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index 667553f74..302e3e81c 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -1,8 +1,11 @@ | |||
1 | pub(super) mod imp; | 1 | pub(super) mod imp; |
2 | pub(crate) mod scope; | 2 | pub(crate) mod scope; |
3 | 3 | ||
4 | use ra_syntax::{ | ||
5 | ast::{self, AstNode, NameOwner}, | ||
6 | SmolStr, SyntaxNode, | ||
7 | }; | ||
4 | use relative_path::RelativePathBuf; | 8 | use relative_path::RelativePathBuf; |
5 | use ra_syntax::{ast::{self, NameOwner, AstNode}, SmolStr, SyntaxNode}; | ||
6 | 9 | ||
7 | use crate::FileId; | 10 | use crate::FileId; |
8 | 11 | ||
@@ -16,9 +19,11 @@ pub(crate) struct ModuleTree { | |||
16 | 19 | ||
17 | impl ModuleTree { | 20 | impl ModuleTree { |
18 | pub(crate) fn modules_for_file(&self, file_id: FileId) -> Vec<ModuleId> { | 21 | pub(crate) fn modules_for_file(&self, file_id: FileId) -> Vec<ModuleId> { |
19 | self.mods.iter() | 22 | self.mods |
23 | .iter() | ||
20 | .enumerate() | 24 | .enumerate() |
21 | .filter(|(_idx, it)| it.file_id == file_id).map(|(idx, _)| ModuleId(idx as u32)) | 25 | .filter(|(_idx, it)| it.file_id == file_id) |
26 | .map(|(idx, _)| ModuleId(idx as u32)) | ||
22 | .collect() | 27 | .collect() |
23 | } | 28 | } |
24 | 29 | ||
@@ -50,7 +55,7 @@ impl ModuleId { | |||
50 | } | 55 | } |
51 | pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { | 56 | pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { |
52 | tree.module(self).parent | 57 | tree.module(self).parent |
53 | } | 58 | } |
54 | pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { | 59 | pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { |
55 | let link = self.parent_link(tree)?; | 60 | let link = self.parent_link(tree)?; |
56 | Some(tree.link(link).owner) | 61 | Some(tree.link(link).owner) |
@@ -69,18 +74,15 @@ impl ModuleId { | |||
69 | curr | 74 | curr |
70 | } | 75 | } |
71 | pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { | 76 | pub(crate) fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { |
72 | let link = tree.module(self) | 77 | let link = tree |
78 | .module(self) | ||
73 | .children | 79 | .children |
74 | .iter() | 80 | .iter() |
75 | .map(|&it| tree.link(it)) | 81 | .map(|&it| tree.link(it)) |
76 | .find(|it| it.name == name)?; | 82 | .find(|it| it.name == name)?; |
77 | Some(*link.points_to.first()?) | 83 | Some(*link.points_to.first()?) |
78 | } | 84 | } |
79 | pub(crate) fn problems( | 85 | pub(crate) fn problems(self, tree: &ModuleTree, root: ast::Root) -> Vec<(SyntaxNode, Problem)> { |
80 | self, | ||
81 | tree: &ModuleTree, | ||
82 | root: ast::Root, | ||
83 | ) -> Vec<(SyntaxNode, Problem)> { | ||
84 | tree.module(self) | 86 | tree.module(self) |
85 | .children | 87 | .children |
86 | .iter() | 88 | .iter() |
@@ -98,11 +100,7 @@ impl LinkId { | |||
98 | pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { | 100 | pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { |
99 | tree.link(self).owner | 101 | tree.link(self).owner |
100 | } | 102 | } |
101 | pub(crate) fn bind_source<'a>( | 103 | pub(crate) fn bind_source<'a>(self, tree: &ModuleTree, root: ast::Root<'a>) -> ast::Module<'a> { |
102 | self, | ||
103 | tree: &ModuleTree, | ||
104 | root: ast::Root<'a>, | ||
105 | ) -> ast::Module<'a> { | ||
106 | imp::modules(root) | 104 | imp::modules(root) |
107 | .find(|(name, _)| name == &tree.link(self).name) | 105 | .find(|(name, _)| name == &tree.link(self).name) |
108 | .unwrap() | 106 | .unwrap() |
@@ -125,7 +123,6 @@ struct LinkData { | |||
125 | problem: Option<Problem>, | 123 | problem: Option<Problem>, |
126 | } | 124 | } |
127 | 125 | ||
128 | |||
129 | impl ModuleTree { | 126 | impl ModuleTree { |
130 | fn module(&self, id: ModuleId) -> &ModuleData { | 127 | fn module(&self, id: ModuleId) -> &ModuleData { |
131 | &self.mods[id.0 as usize] | 128 | &self.mods[id.0 as usize] |
@@ -152,4 +149,3 @@ impl ModuleTree { | |||
152 | id | 149 | id |
153 | } | 150 | } |
154 | } | 151 | } |
155 | |||
diff --git a/crates/ra_analysis/src/descriptors/module/scope.rs b/crates/ra_analysis/src/descriptors/module/scope.rs index 846b8b44f..681e272c2 100644 --- a/crates/ra_analysis/src/descriptors/module/scope.rs +++ b/crates/ra_analysis/src/descriptors/module/scope.rs | |||
@@ -1,9 +1,8 @@ | |||
1 | //! Backend for module-level scope resolution & completion | 1 | //! Backend for module-level scope resolution & completion |
2 | 2 | ||
3 | |||
4 | use ra_syntax::{ | 3 | use ra_syntax::{ |
5 | ast::{self, ModuleItemOwner}, | 4 | ast::{self, ModuleItemOwner}, |
6 | File, AstNode, SmolStr, | 5 | AstNode, File, SmolStr, |
7 | }; | 6 | }; |
8 | 7 | ||
9 | use crate::syntax_ptr::LocalSyntaxPtr; | 8 | use crate::syntax_ptr::LocalSyntaxPtr; |
@@ -103,7 +102,7 @@ fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) { | |||
103 | #[cfg(test)] | 102 | #[cfg(test)] |
104 | mod tests { | 103 | mod tests { |
105 | use super::*; | 104 | use super::*; |
106 | use ra_syntax::{File}; | 105 | use ra_syntax::File; |
107 | 106 | ||
108 | fn do_check(code: &str, expected: &[&str]) { | 107 | fn do_check(code: &str, expected: &[&str]) { |
109 | let file = File::parse(&code); | 108 | let file = File::parse(&code); |
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 1eb8cb912..44077b507 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -13,24 +13,21 @@ use ra_syntax::{ | |||
13 | use rayon::prelude::*; | 13 | use rayon::prelude::*; |
14 | use relative_path::RelativePath; | 14 | use relative_path::RelativePath; |
15 | use rustc_hash::FxHashSet; | 15 | use rustc_hash::FxHashSet; |
16 | use salsa::{ParallelDatabase, Database}; | 16 | use salsa::{Database, ParallelDatabase}; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | AnalysisChange, | 19 | completion::{resolve_based_completion, scope_completion, CompletionItem}, |
20 | db::{ | 20 | db::{self, FileSyntaxQuery, SyntaxDatabase}, |
21 | self, SyntaxDatabase, FileSyntaxQuery, | ||
22 | }, | ||
23 | input::{SourceRootId, FilesDatabase, SourceRoot, WORKSPACE}, | ||
24 | descriptors::{ | 21 | descriptors::{ |
25 | DescriptorDatabase, DeclarationDescriptor, | ||
26 | module::{ModuleTree, Problem}, | ||
27 | function::{FnDescriptor, FnId}, | 22 | function::{FnDescriptor, FnId}, |
23 | module::{ModuleTree, Problem}, | ||
24 | DeclarationDescriptor, DescriptorDatabase, | ||
28 | }, | 25 | }, |
29 | completion::{scope_completion, resolve_based_completion, CompletionItem}, | 26 | input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, |
30 | symbol_index::SymbolIndex, | 27 | symbol_index::SymbolIndex, |
31 | syntax_ptr::SyntaxPtrDatabase, | 28 | syntax_ptr::SyntaxPtrDatabase, |
32 | CrateGraph, CrateId, Diagnostic, FileId, FileResolver, FileSystemEdit, Position, | 29 | AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver, |
33 | Query, SourceChange, SourceFileEdit, Cancelable, | 30 | FileSystemEdit, Position, Query, SourceChange, SourceFileEdit, |
34 | }; | 31 | }; |
35 | 32 | ||
36 | #[derive(Clone, Debug)] | 33 | #[derive(Clone, Debug)] |
@@ -94,7 +91,6 @@ pub(crate) struct AnalysisHostImpl { | |||
94 | db: db::RootDatabase, | 91 | db: db::RootDatabase, |
95 | } | 92 | } |
96 | 93 | ||
97 | |||
98 | impl AnalysisHostImpl { | 94 | impl AnalysisHostImpl { |
99 | pub fn new() -> AnalysisHostImpl { | 95 | pub fn new() -> AnalysisHostImpl { |
100 | let db = db::RootDatabase::default(); | 96 | let db = db::RootDatabase::default(); |
@@ -108,7 +104,7 @@ impl AnalysisHostImpl { | |||
108 | } | 104 | } |
109 | pub fn analysis(&self) -> AnalysisImpl { | 105 | pub fn analysis(&self) -> AnalysisImpl { |
110 | AnalysisImpl { | 106 | AnalysisImpl { |
111 | db: self.db.fork() // freeze revision here | 107 | db: self.db.fork(), // freeze revision here |
112 | } | 108 | } |
113 | } | 109 | } |
114 | pub fn apply_change(&mut self, change: AnalysisChange) { | 110 | pub fn apply_change(&mut self, change: AnalysisChange) { |
@@ -120,7 +116,8 @@ impl AnalysisHostImpl { | |||
120 | .set(file_id, Arc::new(text)) | 116 | .set(file_id, Arc::new(text)) |
121 | } | 117 | } |
122 | if !(change.files_added.is_empty() && change.files_removed.is_empty()) { | 118 | if !(change.files_added.is_empty() && change.files_removed.is_empty()) { |
123 | let file_resolver = change.file_resolver | 119 | let file_resolver = change |
120 | .file_resolver | ||
124 | .expect("change resolver when changing set of files"); | 121 | .expect("change resolver when changing set of files"); |
125 | let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); | 122 | let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); |
126 | for (file_id, text) in change.files_added { | 123 | for (file_id, text) in change.files_added { |
@@ -174,7 +171,8 @@ impl AnalysisHostImpl { | |||
174 | .set((), Arc::new(libraries)); | 171 | .set((), Arc::new(libraries)); |
175 | } | 172 | } |
176 | if let Some(crate_graph) = change.crate_graph { | 173 | if let Some(crate_graph) = change.crate_graph { |
177 | self.db.query(crate::input::CrateGraphQuery) | 174 | self.db |
175 | .query(crate::input::CrateGraphQuery) | ||
178 | .set((), Arc::new(crate_graph)) | 176 | .set((), Arc::new(crate_graph)) |
179 | } | 177 | } |
180 | } | 178 | } |
@@ -194,18 +192,22 @@ impl AnalysisImpl { | |||
194 | } | 192 | } |
195 | pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 193 | pub fn world_symbols(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
196 | let buf: Vec<Arc<SymbolIndex>> = if query.libs { | 194 | let buf: Vec<Arc<SymbolIndex>> = if query.libs { |
197 | self.db.libraries().iter() | 195 | self.db |
196 | .libraries() | ||
197 | .iter() | ||
198 | .map(|&lib_id| self.db.library_symbols(lib_id)) | 198 | .map(|&lib_id| self.db.library_symbols(lib_id)) |
199 | .collect() | 199 | .collect() |
200 | } else { | 200 | } else { |
201 | let files = &self.db.source_root(WORKSPACE).files; | 201 | let files = &self.db.source_root(WORKSPACE).files; |
202 | let db = self.db.clone(); | 202 | let db = self.db.clone(); |
203 | files.par_iter() | 203 | files |
204 | .par_iter() | ||
204 | .map_with(db, |db, &file_id| db.file_symbols(file_id)) | 205 | .map_with(db, |db, &file_id| db.file_symbols(file_id)) |
205 | .filter_map(|it| it.ok()) | 206 | .filter_map(|it| it.ok()) |
206 | .collect() | 207 | .collect() |
207 | }; | 208 | }; |
208 | self.db.query(FileSyntaxQuery) | 209 | self.db |
210 | .query(FileSyntaxQuery) | ||
209 | .sweep(salsa::SweepStrategy::default().discard_values()); | 211 | .sweep(salsa::SweepStrategy::default().discard_values()); |
210 | Ok(query.search(&buf)) | 212 | Ok(query.search(&buf)) |
211 | } | 213 | } |
@@ -216,7 +218,8 @@ impl AnalysisImpl { | |||
216 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 218 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
217 | let module_tree = self.module_tree(file_id)?; | 219 | let module_tree = self.module_tree(file_id)?; |
218 | 220 | ||
219 | let res = module_tree.modules_for_file(file_id) | 221 | let res = module_tree |
222 | .modules_for_file(file_id) | ||
220 | .into_iter() | 223 | .into_iter() |
221 | .filter_map(|module_id| { | 224 | .filter_map(|module_id| { |
222 | let link = module_id.parent_link(&module_tree)?; | 225 | let link = module_id.parent_link(&module_tree)?; |
@@ -237,7 +240,8 @@ impl AnalysisImpl { | |||
237 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 240 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
238 | let module_tree = self.module_tree(file_id)?; | 241 | let module_tree = self.module_tree(file_id)?; |
239 | let crate_graph = self.db.crate_graph(); | 242 | let crate_graph = self.db.crate_graph(); |
240 | let res = module_tree.modules_for_file(file_id) | 243 | let res = module_tree |
244 | .modules_for_file(file_id) | ||
241 | .into_iter() | 245 | .into_iter() |
242 | .map(|it| it.root(&module_tree)) | 246 | .map(|it| it.root(&module_tree)) |
243 | .map(|it| it.file_id(&module_tree)) | 247 | .map(|it| it.file_id(&module_tree)) |
@@ -249,7 +253,11 @@ impl AnalysisImpl { | |||
249 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 253 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
250 | self.db.crate_graph().crate_roots[&crate_id] | 254 | self.db.crate_graph().crate_roots[&crate_id] |
251 | } | 255 | } |
252 | pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { | 256 | pub fn completions( |
257 | &self, | ||
258 | file_id: FileId, | ||
259 | offset: TextUnit, | ||
260 | ) -> Cancelable<Option<Vec<CompletionItem>>> { | ||
253 | let mut res = Vec::new(); | 261 | let mut res = Vec::new(); |
254 | let mut has_completions = false; | 262 | let mut has_completions = false; |
255 | if let Some(scope_based) = scope_completion(&self.db, file_id, offset) { | 263 | if let Some(scope_based) = scope_completion(&self.db, file_id, offset) { |
@@ -260,11 +268,7 @@ impl AnalysisImpl { | |||
260 | res.extend(scope_based); | 268 | res.extend(scope_based); |
261 | has_completions = true; | 269 | has_completions = true; |
262 | } | 270 | } |
263 | let res = if has_completions { | 271 | let res = if has_completions { Some(res) } else { None }; |
264 | Some(res) | ||
265 | } else { | ||
266 | None | ||
267 | }; | ||
268 | Ok(res) | 272 | Ok(res) |
269 | } | 273 | } |
270 | pub fn approximately_resolve_symbol( | 274 | pub fn approximately_resolve_symbol( |
@@ -326,12 +330,11 @@ impl AnalysisImpl { | |||
326 | let syntax = file.syntax(); | 330 | let syntax = file.syntax(); |
327 | 331 | ||
328 | // Find the binding associated with the offset | 332 | // Find the binding associated with the offset |
329 | let maybe_binding = find_node_at_offset::<ast::BindPat>(syntax, offset) | 333 | let maybe_binding = find_node_at_offset::<ast::BindPat>(syntax, offset).or_else(|| { |
330 | .or_else(|| { | 334 | let name_ref = find_node_at_offset::<ast::NameRef>(syntax, offset)?; |
331 | let name_ref = find_node_at_offset::<ast::NameRef>(syntax, offset)?; | 335 | let resolved = resolve_local_name(&self.db, file_id, name_ref)?; |
332 | let resolved = resolve_local_name(&self.db, file_id, name_ref)?; | 336 | find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end()) |
333 | find_node_at_offset::<ast::BindPat>(syntax, resolved.1.end()) | 337 | }); |
334 | }); | ||
335 | 338 | ||
336 | let binding = match maybe_binding { | 339 | let binding = match maybe_binding { |
337 | None => return Vec::new(), | 340 | None => return Vec::new(), |
@@ -341,8 +344,11 @@ impl AnalysisImpl { | |||
341 | let decl = DeclarationDescriptor::new(binding); | 344 | let decl = DeclarationDescriptor::new(binding); |
342 | 345 | ||
343 | let mut ret = vec![(file_id, decl.range)]; | 346 | let mut ret = vec![(file_id, decl.range)]; |
344 | ret.extend(decl.find_all_refs().into_iter() | 347 | ret.extend( |
345 | .map(|ref_desc| (file_id, ref_desc.range ))); | 348 | decl.find_all_refs() |
349 | .into_iter() | ||
350 | .map(|ref_desc| (file_id, ref_desc.range)), | ||
351 | ); | ||
346 | 352 | ||
347 | ret | 353 | ret |
348 | } | 354 | } |
@@ -526,7 +532,8 @@ impl AnalysisImpl { | |||
526 | Some(id) => id, | 532 | Some(id) => id, |
527 | None => return Vec::new(), | 533 | None => return Vec::new(), |
528 | }; | 534 | }; |
529 | module_id.child(module_tree, name.as_str()) | 535 | module_id |
536 | .child(module_tree, name.as_str()) | ||
530 | .map(|it| it.file_id(module_tree)) | 537 | .map(|it| it.file_id(module_tree)) |
531 | .into_iter() | 538 | .into_iter() |
532 | .collect() | 539 | .collect() |
diff --git a/crates/ra_analysis/src/input.rs b/crates/ra_analysis/src/input.rs index b89b45133..ba8a17fd5 100644 --- a/crates/ra_analysis/src/input.rs +++ b/crates/ra_analysis/src/input.rs | |||
@@ -1,12 +1,9 @@ | |||
1 | use std::{ | 1 | use std::{fmt, sync::Arc}; |
2 | sync::Arc, | ||
3 | fmt, | ||
4 | }; | ||
5 | 2 | ||
6 | use salsa; | ||
7 | use rustc_hash::FxHashSet; | ||
8 | use relative_path::RelativePath; | 3 | use relative_path::RelativePath; |
9 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
5 | use rustc_hash::FxHashSet; | ||
6 | use salsa; | ||
10 | 7 | ||
11 | use crate::{symbol_index::SymbolIndex, FileResolverImp}; | 8 | use crate::{symbol_index::SymbolIndex, FileResolverImp}; |
12 | 9 | ||
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index e75411ec9..32aa7a1fd 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -6,23 +6,20 @@ extern crate relative_path; | |||
6 | extern crate rustc_hash; | 6 | extern crate rustc_hash; |
7 | extern crate salsa; | 7 | extern crate salsa; |
8 | 8 | ||
9 | mod input; | 9 | mod completion; |
10 | mod db; | 10 | mod db; |
11 | mod descriptors; | 11 | mod descriptors; |
12 | mod imp; | 12 | mod imp; |
13 | mod input; | ||
14 | pub mod mock_analysis; | ||
13 | mod symbol_index; | 15 | mod symbol_index; |
14 | mod completion; | ||
15 | mod syntax_ptr; | 16 | mod syntax_ptr; |
16 | pub mod mock_analysis; | ||
17 | 17 | ||
18 | use std::{ | 18 | use std::{fmt, sync::Arc}; |
19 | fmt, | ||
20 | sync::Arc, | ||
21 | }; | ||
22 | 19 | ||
23 | use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; | 20 | use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; |
24 | use relative_path::RelativePathBuf; | ||
25 | use rayon::prelude::*; | 21 | use rayon::prelude::*; |
22 | use relative_path::RelativePathBuf; | ||
26 | 23 | ||
27 | use crate::{ | 24 | use crate::{ |
28 | imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}, | 25 | imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}, |
@@ -30,13 +27,12 @@ use crate::{ | |||
30 | }; | 27 | }; |
31 | 28 | ||
32 | pub use crate::{ | 29 | pub use crate::{ |
33 | descriptors::function::FnDescriptor, | ||
34 | completion::CompletionItem, | 30 | completion::CompletionItem, |
35 | input::{FileId, FileResolver, CrateGraph, CrateId}, | 31 | descriptors::function::FnDescriptor, |
32 | input::{CrateGraph, CrateId, FileId, FileResolver}, | ||
36 | }; | 33 | }; |
37 | pub use ra_editor::{ | 34 | pub use ra_editor::{ |
38 | FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, | 35 | FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode, |
39 | RunnableKind, StructureNode, | ||
40 | }; | 36 | }; |
41 | 37 | ||
42 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 38 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
@@ -50,8 +46,7 @@ impl std::fmt::Display for Canceled { | |||
50 | } | 46 | } |
51 | } | 47 | } |
52 | 48 | ||
53 | impl std::error::Error for Canceled { | 49 | impl std::error::Error for Canceled {} |
54 | } | ||
55 | 50 | ||
56 | #[derive(Default)] | 51 | #[derive(Default)] |
57 | pub struct AnalysisChange { | 52 | pub struct AnalysisChange { |
@@ -76,7 +71,6 @@ impl fmt::Debug for AnalysisChange { | |||
76 | } | 71 | } |
77 | } | 72 | } |
78 | 73 | ||
79 | |||
80 | impl AnalysisChange { | 74 | impl AnalysisChange { |
81 | pub fn new() -> AnalysisChange { | 75 | pub fn new() -> AnalysisChange { |
82 | AnalysisChange::default() | 76 | AnalysisChange::default() |
@@ -251,12 +245,15 @@ impl Analysis { | |||
251 | pub fn approximately_resolve_symbol( | 245 | pub fn approximately_resolve_symbol( |
252 | &self, | 246 | &self, |
253 | file_id: FileId, | 247 | file_id: FileId, |
254 | offset: TextUnit | 248 | offset: TextUnit, |
255 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 249 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
256 | self.imp | 250 | self.imp.approximately_resolve_symbol(file_id, offset) |
257 | .approximately_resolve_symbol(file_id, offset) | ||
258 | } | 251 | } |
259 | pub fn find_all_refs(&self, file_id: FileId, offset: TextUnit, ) -> Cancelable<Vec<(FileId, TextRange)>> { | 252 | pub fn find_all_refs( |
253 | &self, | ||
254 | file_id: FileId, | ||
255 | offset: TextUnit, | ||
256 | ) -> Cancelable<Vec<(FileId, TextRange)>> { | ||
260 | Ok(self.imp.find_all_refs(file_id, offset)) | 257 | Ok(self.imp.find_all_refs(file_id, offset)) |
261 | } | 258 | } |
262 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 259 | pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
@@ -276,7 +273,11 @@ impl Analysis { | |||
276 | let file = self.imp.file_syntax(file_id); | 273 | let file = self.imp.file_syntax(file_id); |
277 | Ok(ra_editor::highlight(&file)) | 274 | Ok(ra_editor::highlight(&file)) |
278 | } | 275 | } |
279 | pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { | 276 | pub fn completions( |
277 | &self, | ||
278 | file_id: FileId, | ||
279 | offset: TextUnit, | ||
280 | ) -> Cancelable<Option<Vec<CompletionItem>>> { | ||
280 | self.imp.completions(file_id, offset) | 281 | self.imp.completions(file_id, offset) |
281 | } | 282 | } |
282 | pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> { | 283 | pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> { |
@@ -307,7 +308,11 @@ impl LibraryData { | |||
307 | let file = File::parse(text); | 308 | let file = File::parse(text); |
308 | (*file_id, file) | 309 | (*file_id, file) |
309 | })); | 310 | })); |
310 | LibraryData { files, file_resolver: FileResolverImp::new(file_resolver), symbol_index } | 311 | LibraryData { |
312 | files, | ||
313 | file_resolver: FileResolverImp::new(file_resolver), | ||
314 | symbol_index, | ||
315 | } | ||
311 | } | 316 | } |
312 | } | 317 | } |
313 | 318 | ||
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs index f72911192..76100f548 100644 --- a/crates/ra_analysis/src/mock_analysis.rs +++ b/crates/ra_analysis/src/mock_analysis.rs | |||
@@ -1,13 +1,10 @@ | |||
1 | |||
2 | use std::sync::Arc; | 1 | use std::sync::Arc; |
3 | 2 | ||
4 | use relative_path::{RelativePath, RelativePathBuf}; | ||
5 | use ra_syntax::TextUnit; | 3 | use ra_syntax::TextUnit; |
4 | use relative_path::{RelativePath, RelativePathBuf}; | ||
6 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | 5 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; |
7 | 6 | ||
8 | use crate::{ | 7 | use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FileResolver}; |
9 | AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver, | ||
10 | }; | ||
11 | 8 | ||
12 | #[derive(Debug)] | 9 | #[derive(Debug)] |
13 | pub struct FilePosition { | 10 | pub struct FilePosition { |
@@ -51,7 +48,10 @@ impl MockAnalysis { | |||
51 | let mut res = MockAnalysis::new(); | 48 | let mut res = MockAnalysis::new(); |
52 | for entry in parse_fixture(fixture) { | 49 | for entry in parse_fixture(fixture) { |
53 | if entry.text.contains(CURSOR_MARKER) { | 50 | if entry.text.contains(CURSOR_MARKER) { |
54 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); | 51 | assert!( |
52 | position.is_none(), | ||
53 | "only one marker (<|>) per fixture is allowed" | ||
54 | ); | ||
55 | position = Some(res.add_file_with_position(&entry.meta, &entry.text)); | 55 | position = Some(res.add_file_with_position(&entry.meta, &entry.text)); |
56 | } else { | 56 | } else { |
57 | res.add_file(&entry.meta, &entry.text); | 57 | res.add_file(&entry.meta, &entry.text); |
@@ -73,7 +73,10 @@ impl MockAnalysis { | |||
73 | FilePosition { file_id, offset } | 73 | FilePosition { file_id, offset } |
74 | } | 74 | } |
75 | pub fn id_of(&self, path: &str) -> FileId { | 75 | pub fn id_of(&self, path: &str) -> FileId { |
76 | let (idx, _) = self.files.iter().enumerate() | 76 | let (idx, _) = self |
77 | .files | ||
78 | .iter() | ||
79 | .enumerate() | ||
77 | .find(|(_, (p, _text))| path == p) | 80 | .find(|(_, (p, _text))| path == p) |
78 | .expect("no file in this mock"); | 81 | .expect("no file in this mock"); |
79 | FileId(idx as u32 + 1) | 82 | FileId(idx as u32 + 1) |
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index 5f302cbda..b57ad5d33 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs | |||
@@ -57,10 +57,7 @@ impl SymbolIndex { | |||
57 | } | 57 | } |
58 | 58 | ||
59 | impl Query { | 59 | impl Query { |
60 | pub(crate) fn search( | 60 | pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<(FileId, FileSymbol)> { |
61 | self, | ||
62 | indices: &[Arc<SymbolIndex>], | ||
63 | ) -> Vec<(FileId, FileSymbol)> { | ||
64 | let mut op = fst::map::OpBuilder::new(); | 61 | let mut op = fst::map::OpBuilder::new(); |
65 | for file_symbols in indices.iter() { | 62 | for file_symbols in indices.iter() { |
66 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); | 63 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); |
diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_analysis/src/syntax_ptr.rs index c3c904633..612f75cd9 100644 --- a/crates/ra_analysis/src/syntax_ptr.rs +++ b/crates/ra_analysis/src/syntax_ptr.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | use std::marker::PhantomData; | 1 | use std::marker::PhantomData; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | File, TextRange, SyntaxKind, SyntaxNode, SyntaxNodeRef, | ||
5 | ast::{self, AstNode}, | 4 | ast::{self, AstNode}, |
5 | File, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange, | ||
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::FileId; | ||
9 | use crate::db::SyntaxDatabase; | 8 | use crate::db::SyntaxDatabase; |
9 | use crate::FileId; | ||
10 | 10 | ||
11 | salsa::query_group! { | 11 | salsa::query_group! { |
12 | pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase { | 12 | pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase { |
@@ -52,12 +52,10 @@ trait ToAst { | |||
52 | impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> { | 52 | impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> { |
53 | type Ast = ast::FnDef<'a>; | 53 | type Ast = ast::FnDef<'a>; |
54 | fn to_ast(self) -> ast::FnDef<'a> { | 54 | fn to_ast(self) -> ast::FnDef<'a> { |
55 | ast::FnDef::cast(self.syntax.borrowed()) | 55 | ast::FnDef::cast(self.syntax.borrowed()).unwrap() |
56 | .unwrap() | ||
57 | } | 56 | } |
58 | } | 57 | } |
59 | 58 | ||
60 | |||
61 | /// A pionter to a syntax node inside a file. | 59 | /// A pionter to a syntax node inside a file. |
62 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 60 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
63 | pub(crate) struct LocalSyntaxPtr { | 61 | pub(crate) struct LocalSyntaxPtr { |
@@ -79,22 +77,29 @@ impl LocalSyntaxPtr { | |||
79 | if curr.range() == self.range && curr.kind() == self.kind { | 77 | if curr.range() == self.range && curr.kind() == self.kind { |
80 | return curr.owned(); | 78 | return curr.owned(); |
81 | } | 79 | } |
82 | curr = curr.children() | 80 | curr = curr |
81 | .children() | ||
83 | .find(|it| self.range.is_subrange(&it.range())) | 82 | .find(|it| self.range.is_subrange(&it.range())) |
84 | .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) | 83 | .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) |
85 | } | 84 | } |
86 | } | 85 | } |
87 | 86 | ||
88 | pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr { | 87 | pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr { |
89 | SyntaxPtr { file_id, local: self} | 88 | SyntaxPtr { |
89 | file_id, | ||
90 | local: self, | ||
91 | } | ||
90 | } | 92 | } |
91 | } | 93 | } |
92 | 94 | ||
93 | |||
94 | #[test] | 95 | #[test] |
95 | fn test_local_syntax_ptr() { | 96 | fn test_local_syntax_ptr() { |
96 | let file = File::parse("struct Foo { f: u32, }"); | 97 | let file = File::parse("struct Foo { f: u32, }"); |
97 | let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap(); | 98 | let field = file |
99 | .syntax() | ||
100 | .descendants() | ||
101 | .find_map(ast::NamedFieldDef::cast) | ||
102 | .unwrap(); | ||
98 | let ptr = LocalSyntaxPtr::new(field.syntax()); | 103 | let ptr = LocalSyntaxPtr::new(field.syntax()); |
99 | let field_syntax = ptr.resolve(&file); | 104 | let field_syntax = ptr.resolve(&file); |
100 | assert_eq!(field.syntax(), field_syntax); | 105 | assert_eq!(field.syntax(), field_syntax); |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 22d27cdbe..c2754c8e4 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -5,42 +5,53 @@ extern crate relative_path; | |||
5 | extern crate rustc_hash; | 5 | extern crate rustc_hash; |
6 | extern crate test_utils; | 6 | extern crate test_utils; |
7 | 7 | ||
8 | use ra_syntax::{TextRange}; | 8 | use ra_syntax::TextRange; |
9 | use test_utils::{assert_eq_dbg}; | 9 | use test_utils::assert_eq_dbg; |
10 | 10 | ||
11 | use ra_analysis::{ | 11 | use ra_analysis::{ |
12 | mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis}, | ||
12 | AnalysisChange, CrateGraph, FileId, FnDescriptor, | 13 | AnalysisChange, CrateGraph, FileId, FnDescriptor, |
13 | mock_analysis::{MockAnalysis, single_file, single_file_with_position, analysis_and_position}, | ||
14 | }; | 14 | }; |
15 | 15 | ||
16 | fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) { | 16 | fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) { |
17 | let (analysis, position) = single_file_with_position(text); | 17 | let (analysis, position) = single_file_with_position(text); |
18 | analysis.resolve_callable(position.file_id, position.offset).unwrap().unwrap() | 18 | analysis |
19 | .resolve_callable(position.file_id, position.offset) | ||
20 | .unwrap() | ||
21 | .unwrap() | ||
19 | } | 22 | } |
20 | 23 | ||
21 | #[test] | 24 | #[test] |
22 | fn test_resolve_module() { | 25 | fn test_resolve_module() { |
23 | let (analysis, pos) = analysis_and_position(" | 26 | let (analysis, pos) = analysis_and_position( |
27 | " | ||
24 | //- /lib.rs | 28 | //- /lib.rs |
25 | mod <|>foo; | 29 | mod <|>foo; |
26 | //- /foo.rs | 30 | //- /foo.rs |
27 | // empty | 31 | // empty |
28 | "); | 32 | ", |
33 | ); | ||
29 | 34 | ||
30 | let symbols = analysis.approximately_resolve_symbol(pos.file_id, pos.offset).unwrap(); | 35 | let symbols = analysis |
36 | .approximately_resolve_symbol(pos.file_id, pos.offset) | ||
37 | .unwrap(); | ||
31 | assert_eq_dbg( | 38 | assert_eq_dbg( |
32 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 39 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, |
33 | &symbols, | 40 | &symbols, |
34 | ); | 41 | ); |
35 | 42 | ||
36 | let (analysis, pos) = analysis_and_position(" | 43 | let (analysis, pos) = analysis_and_position( |
44 | " | ||
37 | //- /lib.rs | 45 | //- /lib.rs |
38 | mod <|>foo; | 46 | mod <|>foo; |
39 | //- /foo/mod.rs | 47 | //- /foo/mod.rs |
40 | // empty | 48 | // empty |
41 | "); | 49 | ", |
50 | ); | ||
42 | 51 | ||
43 | let symbols = analysis.approximately_resolve_symbol(pos.file_id, pos.offset).unwrap(); | 52 | let symbols = analysis |
53 | .approximately_resolve_symbol(pos.file_id, pos.offset) | ||
54 | .unwrap(); | ||
44 | assert_eq_dbg( | 55 | assert_eq_dbg( |
45 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 56 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, |
46 | &symbols, | 57 | &symbols, |
@@ -73,12 +84,14 @@ fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() { | |||
73 | 84 | ||
74 | #[test] | 85 | #[test] |
75 | fn test_resolve_parent_module() { | 86 | fn test_resolve_parent_module() { |
76 | let (analysis, pos) = analysis_and_position(" | 87 | let (analysis, pos) = analysis_and_position( |
88 | " | ||
77 | //- /lib.rs | 89 | //- /lib.rs |
78 | mod foo; | 90 | mod foo; |
79 | //- /foo.rs | 91 | //- /foo.rs |
80 | <|>// empty | 92 | <|>// empty |
81 | "); | 93 | ", |
94 | ); | ||
82 | let symbols = analysis.parent_module(pos.file_id).unwrap(); | 95 | let symbols = analysis.parent_module(pos.file_id).unwrap(); |
83 | assert_eq_dbg( | 96 | assert_eq_dbg( |
84 | r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, | 97 | r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#, |
@@ -88,12 +101,14 @@ fn test_resolve_parent_module() { | |||
88 | 101 | ||
89 | #[test] | 102 | #[test] |
90 | fn test_resolve_crate_root() { | 103 | fn test_resolve_crate_root() { |
91 | let mock = MockAnalysis::with_files(" | 104 | let mock = MockAnalysis::with_files( |
105 | " | ||
92 | //- /lib.rs | 106 | //- /lib.rs |
93 | mod foo; | 107 | mod foo; |
94 | //- /foo.rs | 108 | //- /foo.rs |
95 | // emtpy <|> | 109 | // emtpy <|> |
96 | "); | 110 | ", |
111 | ); | ||
97 | let root_file = mock.id_of("/lib.rs"); | 112 | let root_file = mock.id_of("/lib.rs"); |
98 | let mod_file = mock.id_of("/foo.rs"); | 113 | let mod_file = mock.id_of("/foo.rs"); |
99 | let mut host = mock.analysis_host(); | 114 | let mut host = mock.analysis_host(); |
@@ -245,8 +260,10 @@ pub fn do() { | |||
245 | assert_eq!(desc.ret_type, Some("-> i32".to_string())); | 260 | assert_eq!(desc.ret_type, Some("-> i32".to_string())); |
246 | assert_eq!(param, Some(0)); | 261 | assert_eq!(param, Some(0)); |
247 | assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); | 262 | assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); |
248 | assert_eq!(desc.doc, Some( | 263 | assert_eq!( |
249 | r#"Adds one to the number given. | 264 | desc.doc, |
265 | Some( | ||
266 | r#"Adds one to the number given. | ||
250 | 267 | ||
251 | # Examples | 268 | # Examples |
252 | 269 | ||
@@ -254,7 +271,10 @@ r#"Adds one to the number given. | |||
254 | let five = 5; | 271 | let five = 5; |
255 | 272 | ||
256 | assert_eq!(6, my_crate::add_one(5)); | 273 | assert_eq!(6, my_crate::add_one(5)); |
257 | ```"#.into())); | 274 | ```"# |
275 | .into() | ||
276 | ) | ||
277 | ); | ||
258 | } | 278 | } |
259 | 279 | ||
260 | #[test] | 280 | #[test] |
@@ -280,15 +300,18 @@ impl addr { | |||
280 | pub fn do_it() { | 300 | pub fn do_it() { |
281 | addr {}; | 301 | addr {}; |
282 | addr::add_one(<|>); | 302 | addr::add_one(<|>); |
283 | }"#); | 303 | }"#, |
304 | ); | ||
284 | 305 | ||
285 | assert_eq!(desc.name, "add_one".to_string()); | 306 | assert_eq!(desc.name, "add_one".to_string()); |
286 | assert_eq!(desc.params, vec!["x".to_string()]); | 307 | assert_eq!(desc.params, vec!["x".to_string()]); |
287 | assert_eq!(desc.ret_type, Some("-> i32".to_string())); | 308 | assert_eq!(desc.ret_type, Some("-> i32".to_string())); |
288 | assert_eq!(param, Some(0)); | 309 | assert_eq!(param, Some(0)); |
289 | assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); | 310 | assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); |
290 | assert_eq!(desc.doc, Some( | 311 | assert_eq!( |
291 | r#"Adds one to the number given. | 312 | desc.doc, |
313 | Some( | ||
314 | r#"Adds one to the number given. | ||
292 | 315 | ||
293 | # Examples | 316 | # Examples |
294 | 317 | ||
@@ -296,7 +319,10 @@ r#"Adds one to the number given. | |||
296 | let five = 5; | 319 | let five = 5; |
297 | 320 | ||
298 | assert_eq!(6, my_crate::add_one(5)); | 321 | assert_eq!(6, my_crate::add_one(5)); |
299 | ```"#.into())); | 322 | ```"# |
323 | .into() | ||
324 | ) | ||
325 | ); | ||
300 | } | 326 | } |
301 | 327 | ||
302 | #[test] | 328 | #[test] |
@@ -329,22 +355,32 @@ pub fn foo() { | |||
329 | r.finished(<|>); | 355 | r.finished(<|>); |
330 | } | 356 | } |
331 | 357 | ||
332 | "#); | 358 | "#, |
359 | ); | ||
333 | 360 | ||
334 | assert_eq!(desc.name, "finished".to_string()); | 361 | assert_eq!(desc.name, "finished".to_string()); |
335 | assert_eq!(desc.params, vec!["&mut self".to_string(), "ctx".to_string()]); | 362 | assert_eq!( |
363 | desc.params, | ||
364 | vec!["&mut self".to_string(), "ctx".to_string()] | ||
365 | ); | ||
336 | assert_eq!(desc.ret_type, None); | 366 | assert_eq!(desc.ret_type, None); |
337 | assert_eq!(param, Some(1)); | 367 | assert_eq!(param, Some(1)); |
338 | assert_eq!(desc.doc, Some( | 368 | assert_eq!( |
339 | r#"Method is called when writer finishes. | 369 | desc.doc, |
340 | 370 | Some( | |
341 | By default this method stops actor's `Context`."#.into())); | 371 | r#"Method is called when writer finishes. |
372 | |||
373 | By default this method stops actor's `Context`."# | ||
374 | .into() | ||
375 | ) | ||
376 | ); | ||
342 | } | 377 | } |
343 | 378 | ||
344 | |||
345 | fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> { | 379 | fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> { |
346 | let (analysis, position) = single_file_with_position(text); | 380 | let (analysis, position) = single_file_with_position(text); |
347 | analysis.find_all_refs(position.file_id, position.offset).unwrap() | 381 | analysis |
382 | .find_all_refs(position.file_id, position.offset) | ||
383 | .unwrap() | ||
348 | } | 384 | } |
349 | 385 | ||
350 | #[test] | 386 | #[test] |
@@ -390,14 +426,19 @@ fn test_find_all_refs_for_fn_param() { | |||
390 | 426 | ||
391 | #[test] | 427 | #[test] |
392 | fn test_complete_crate_path() { | 428 | fn test_complete_crate_path() { |
393 | let (analysis, position) = analysis_and_position(" | 429 | let (analysis, position) = analysis_and_position( |
430 | " | ||
394 | //- /lib.rs | 431 | //- /lib.rs |
395 | mod foo; | 432 | mod foo; |
396 | struct Spam; | 433 | struct Spam; |
397 | //- /foo.rs | 434 | //- /foo.rs |
398 | use crate::Sp<|> | 435 | use crate::Sp<|> |
399 | "); | 436 | ", |
400 | let completions = analysis.completions(position.file_id, position.offset).unwrap().unwrap(); | 437 | ); |
438 | let completions = analysis | ||
439 | .completions(position.file_id, position.offset) | ||
440 | .unwrap() | ||
441 | .unwrap(); | ||
401 | assert_eq_dbg( | 442 | assert_eq_dbg( |
402 | r#"[CompletionItem { label: "foo", lookup: None, snippet: None }, | 443 | r#"[CompletionItem { label: "foo", lookup: None, snippet: None }, |
403 | CompletionItem { label: "Spam", lookup: None, snippet: None }]"#, | 444 | CompletionItem { label: "Spam", lookup: None, snippet: None }]"#, |
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs index 8b79ea874..0803c8891 100644 --- a/crates/ra_editor/src/folding_ranges.rs +++ b/crates/ra_editor/src/folding_ranges.rs | |||
@@ -174,8 +174,16 @@ mod tests { | |||
174 | let file = File::parse(&text); | 174 | let file = File::parse(&text); |
175 | let folds = folding_ranges(&file); | 175 | let folds = folding_ranges(&file); |
176 | 176 | ||
177 | assert_eq!(folds.len(), ranges.len(), "The amount of folds is different than the expected amount"); | 177 | assert_eq!( |
178 | assert_eq!(folds.len(), fold_kinds.len(), "The amount of fold kinds is different than the expected amount"); | 178 | folds.len(), |
179 | ranges.len(), | ||
180 | "The amount of folds is different than the expected amount" | ||
181 | ); | ||
182 | assert_eq!( | ||
183 | folds.len(), | ||
184 | fold_kinds.len(), | ||
185 | "The amount of fold kinds is different than the expected amount" | ||
186 | ); | ||
179 | for ((fold, range), fold_kind) in folds | 187 | for ((fold, range), fold_kind) in folds |
180 | .into_iter() | 188 | .into_iter() |
181 | .zip(ranges.into_iter()) | 189 | .zip(ranges.into_iter()) |
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index 02a1b2d45..481f4c9fc 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs | |||
@@ -148,8 +148,6 @@ pub fn find_node_at_offset<'a, N: AstNode<'a>>( | |||
148 | leaf.ancestors().filter_map(N::cast).next() | 148 | leaf.ancestors().filter_map(N::cast).next() |
149 | } | 149 | } |
150 | 150 | ||
151 | |||
152 | |||
153 | #[cfg(test)] | 151 | #[cfg(test)] |
154 | mod tests { | 152 | mod tests { |
155 | use super::*; | 153 | use super::*; |
diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index 0bab9dd67..4e602d0e3 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs | |||
@@ -1,12 +1,9 @@ | |||
1 | use crate::TextRange; | 1 | use crate::TextRange; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | algo::{ | 4 | algo::visit::{visitor, Visitor}, |
5 | visit::{visitor, Visitor}, | ||
6 | }, | ||
7 | ast::{self, NameOwner}, | 5 | ast::{self, NameOwner}, |
8 | AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef, | 6 | AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent, |
9 | WalkEvent, | ||
10 | }; | 7 | }; |
11 | 8 | ||
12 | #[derive(Debug, Clone)] | 9 | #[derive(Debug, Clone)] |
@@ -54,7 +51,6 @@ pub fn file_structure(file: &File) -> Vec<StructureNode> { | |||
54 | let mut res = Vec::new(); | 51 | let mut res = Vec::new(); |
55 | let mut stack = Vec::new(); | 52 | let mut stack = Vec::new(); |
56 | 53 | ||
57 | |||
58 | for event in file.syntax().preorder() { | 54 | for event in file.syntax().preorder() { |
59 | match event { | 55 | match event { |
60 | WalkEvent::Enter(node) => { | 56 | WalkEvent::Enter(node) => { |
@@ -63,7 +59,7 @@ pub fn file_structure(file: &File) -> Vec<StructureNode> { | |||
63 | stack.push(res.len()); | 59 | stack.push(res.len()); |
64 | res.push(symbol); | 60 | res.push(symbol); |
65 | } | 61 | } |
66 | }, | 62 | } |
67 | WalkEvent::Leave(node) => { | 63 | WalkEvent::Leave(node) => { |
68 | if structure_node(node).is_some() { | 64 | if structure_node(node).is_some() { |
69 | stack.pop().unwrap(); | 65 | stack.pop().unwrap(); |
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index b6436b646..ac6aacfd3 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use languageserver_types::{ | 1 | use languageserver_types::{ |
2 | CodeActionProviderCapability, CompletionOptions, DocumentOnTypeFormattingOptions, | 2 | CodeActionProviderCapability, CompletionOptions, DocumentOnTypeFormattingOptions, |
3 | ExecuteCommandOptions, FoldingRangeProviderCapability, ServerCapabilities, | 3 | ExecuteCommandOptions, FoldingRangeProviderCapability, RenameOptions, RenameProviderCapability, |
4 | SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, | 4 | ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, |
5 | TextDocumentSyncOptions, RenameProviderCapability, RenameOptions | 5 | TextDocumentSyncOptions, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | pub fn server_capabilities() -> ServerCapabilities { | 8 | pub fn server_capabilities() -> ServerCapabilities { |
@@ -40,8 +40,8 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
40 | more_trigger_character: None, | 40 | more_trigger_character: None, |
41 | }), | 41 | }), |
42 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), | 42 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), |
43 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions{ | 43 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions { |
44 | prepare_provider: Some(true) | 44 | prepare_provider: Some(true), |
45 | })), | 45 | })), |
46 | color_provider: None, | 46 | color_provider: None, |
47 | execute_command_provider: Some(ExecuteCommandOptions { | 47 | execute_command_provider: Some(ExecuteCommandOptions { |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index bc0cf7c68..84ffac2da 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -192,7 +192,8 @@ impl TryConvWith for SourceChange { | |||
192 | .map(|it| it.edits.as_slice()) | 192 | .map(|it| it.edits.as_slice()) |
193 | .unwrap_or(&[]); | 193 | .unwrap_or(&[]); |
194 | let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits); | 194 | let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits); |
195 | let position = Position::new(u64::from(line_col.line), u64::from(u32::from(line_col.col))); | 195 | let position = |
196 | Position::new(u64::from(line_col.line), u64::from(u32::from(line_col.col))); | ||
196 | Some(TextDocumentPositionParams { | 197 | Some(TextDocumentPositionParams { |
197 | text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?), | 198 | text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?), |
198 | position, | 199 | position, |
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index ce77b2a33..f9481e04d 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -36,4 +36,4 @@ pub mod thread_watcher; | |||
36 | mod vfs; | 36 | mod vfs; |
37 | 37 | ||
38 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 38 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
39 | pub use crate::{caps::server_capabilities, main_loop::main_loop, main_loop::LspError}; \ No newline at end of file | 39 | pub use crate::{caps::server_capabilities, main_loop::main_loop, main_loop::LspError}; |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 20cb5f772..c853ff653 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -1,15 +1,16 @@ | |||
1 | use std::collections::HashMap; | 1 | use std::collections::HashMap; |
2 | 2 | ||
3 | use rustc_hash::FxHashMap; | 3 | use gen_lsp_server::ErrorCode; |
4 | use languageserver_types::{ | 4 | use languageserver_types::{ |
5 | CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, | 5 | CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, |
6 | DiagnosticSeverity, DocumentSymbol, FoldingRange, FoldingRangeKind, FoldingRangeParams, | 6 | DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, |
7 | InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit, | 7 | FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, Position, |
8 | RenameParams, WorkspaceEdit, PrepareRenameResponse, Documentation, MarkupContent, MarkupKind | 8 | PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, |
9 | WorkspaceEdit, | ||
9 | }; | 10 | }; |
10 | use gen_lsp_server::ErrorCode; | ||
11 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; | 11 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; |
12 | use ra_syntax::text_utils::contains_offset_nonstrict; | 12 | use ra_syntax::text_utils::contains_offset_nonstrict; |
13 | use rustc_hash::FxHashMap; | ||
13 | use serde_json::to_value; | 14 | use serde_json::to_value; |
14 | 15 | ||
15 | use crate::{ | 16 | use crate::{ |
@@ -17,13 +18,10 @@ use crate::{ | |||
17 | project_model::TargetKind, | 18 | project_model::TargetKind, |
18 | req::{self, Decoration}, | 19 | req::{self, Decoration}, |
19 | server_world::ServerWorld, | 20 | server_world::ServerWorld, |
20 | Result, LspError | 21 | LspError, Result, |
21 | }; | 22 | }; |
22 | 23 | ||
23 | pub fn handle_syntax_tree( | 24 | pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result<String> { |
24 | world: ServerWorld, | ||
25 | params: req::SyntaxTreeParams, | ||
26 | ) -> Result<String> { | ||
27 | let id = params.text_document.try_conv_with(&world)?; | 25 | let id = params.text_document.try_conv_with(&world)?; |
28 | let res = world.analysis().syntax_tree(id); | 26 | let res = world.analysis().syntax_tree(id); |
29 | Ok(res) | 27 | Ok(res) |
@@ -182,10 +180,7 @@ pub fn handle_workspace_symbol( | |||
182 | 180 | ||
183 | return Ok(Some(res)); | 181 | return Ok(Some(res)); |
184 | 182 | ||
185 | fn exec_query( | 183 | fn exec_query(world: &ServerWorld, query: Query) -> Result<Vec<SymbolInformation>> { |
186 | world: &ServerWorld, | ||
187 | query: Query, | ||
188 | ) -> Result<Vec<SymbolInformation>> { | ||
189 | let mut res = Vec::new(); | 184 | let mut res = Vec::new(); |
190 | for (file_id, symbol) in world.analysis().symbol_search(query)? { | 185 | for (file_id, symbol) in world.analysis().symbol_search(query)? { |
191 | let line_index = world.analysis().file_line_index(file_id); | 186 | let line_index = world.analysis().file_line_index(file_id); |
@@ -290,7 +285,11 @@ pub fn handle_runnables( | |||
290 | }); | 285 | }); |
291 | return Ok(res); | 286 | return Ok(res); |
292 | 287 | ||
293 | fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Result<Vec<String>> { | 288 | fn runnable_args( |
289 | world: &ServerWorld, | ||
290 | file_id: FileId, | ||
291 | kind: &RunnableKind, | ||
292 | ) -> Result<Vec<String>> { | ||
294 | let spec = CargoTargetSpec::for_file(world, file_id)?; | 293 | let spec = CargoTargetSpec::for_file(world, file_id)?; |
295 | let mut res = Vec::new(); | 294 | let mut res = Vec::new(); |
296 | match kind { | 295 | match kind { |
@@ -327,18 +326,15 @@ pub fn handle_runnables( | |||
327 | }; | 326 | }; |
328 | let file_id = world.analysis().crate_root(crate_id)?; | 327 | let file_id = world.analysis().crate_root(crate_id)?; |
329 | let path = world.path_map.get_path(file_id); | 328 | let path = world.path_map.get_path(file_id); |
330 | let res = world | 329 | let res = world.workspaces.iter().find_map(|ws| { |
331 | .workspaces | 330 | let tgt = ws.target_by_root(path)?; |
332 | .iter() | 331 | let res = CargoTargetSpec { |
333 | .find_map(|ws| { | 332 | package: tgt.package(ws).name(ws).to_string(), |
334 | let tgt = ws.target_by_root(path)?; | 333 | target: tgt.name(ws).to_string(), |
335 | let res = CargoTargetSpec { | 334 | target_kind: tgt.kind(ws), |
336 | package: tgt.package(ws).name(ws).to_string(), | 335 | }; |
337 | target: tgt.name(ws).to_string(), | 336 | Some(res) |
338 | target_kind: tgt.kind(ws), | 337 | }); |
339 | }; | ||
340 | Some(res) | ||
341 | }); | ||
342 | Ok(res) | 338 | Ok(res) |
343 | } | 339 | } |
344 | 340 | ||
@@ -367,7 +363,6 @@ pub fn handle_runnables( | |||
367 | } | 363 | } |
368 | TargetKind::Other => (), | 364 | TargetKind::Other => (), |
369 | } | 365 | } |
370 | |||
371 | } | 366 | } |
372 | } | 367 | } |
373 | } | 368 | } |
@@ -453,9 +448,7 @@ pub fn handle_signature_help( | |||
453 | let line_index = world.analysis().file_line_index(file_id); | 448 | let line_index = world.analysis().file_line_index(file_id); |
454 | let offset = params.position.conv_with(&line_index); | 449 | let offset = params.position.conv_with(&line_index); |
455 | 450 | ||
456 | if let Some((descriptor, active_param)) = | 451 | if let Some((descriptor, active_param)) = world.analysis().resolve_callable(file_id, offset)? { |
457 | world.analysis().resolve_callable(file_id, offset)? | ||
458 | { | ||
459 | let parameters: Vec<ParameterInformation> = descriptor | 452 | let parameters: Vec<ParameterInformation> = descriptor |
460 | .params | 453 | .params |
461 | .iter() | 454 | .iter() |
@@ -468,7 +461,7 @@ pub fn handle_signature_help( | |||
468 | let documentation = if let Some(doc) = descriptor.doc { | 461 | let documentation = if let Some(doc) = descriptor.doc { |
469 | Some(Documentation::MarkupContent(MarkupContent { | 462 | Some(Documentation::MarkupContent(MarkupContent { |
470 | kind: MarkupKind::Markdown, | 463 | kind: MarkupKind::Markdown, |
471 | value: doc | 464 | value: doc, |
472 | })) | 465 | })) |
473 | } else { | 466 | } else { |
474 | None | 467 | None |
@@ -511,16 +504,17 @@ pub fn handle_prepare_rename( | |||
511 | Ok(Some(PrepareRenameResponse::Range(loc.range))) | 504 | Ok(Some(PrepareRenameResponse::Range(loc.range))) |
512 | } | 505 | } |
513 | 506 | ||
514 | pub fn handle_rename( | 507 | pub fn handle_rename(world: ServerWorld, params: RenameParams) -> Result<Option<WorkspaceEdit>> { |
515 | world: ServerWorld, | ||
516 | params: RenameParams, | ||
517 | ) -> Result<Option<WorkspaceEdit>> { | ||
518 | let file_id = params.text_document.try_conv_with(&world)?; | 508 | let file_id = params.text_document.try_conv_with(&world)?; |
519 | let line_index = world.analysis().file_line_index(file_id); | 509 | let line_index = world.analysis().file_line_index(file_id); |
520 | let offset = params.position.conv_with(&line_index); | 510 | let offset = params.position.conv_with(&line_index); |
521 | 511 | ||
522 | if params.new_name.is_empty() { | 512 | if params.new_name.is_empty() { |
523 | return Err(LspError::new(ErrorCode::InvalidParams as i32, "New Name cannot be empty".into()).into()); | 513 | return Err(LspError::new( |
514 | ErrorCode::InvalidParams as i32, | ||
515 | "New Name cannot be empty".into(), | ||
516 | ) | ||
517 | .into()); | ||
524 | } | 518 | } |
525 | 519 | ||
526 | let refs = world.analysis().find_all_refs(file_id, offset)?; | 520 | let refs = world.analysis().find_all_refs(file_id, offset)?; |
@@ -531,11 +525,10 @@ pub fn handle_rename( | |||
531 | let mut changes = HashMap::new(); | 525 | let mut changes = HashMap::new(); |
532 | for r in refs { | 526 | for r in refs { |
533 | if let Ok(loc) = to_location(r.0, r.1, &world, &line_index) { | 527 | if let Ok(loc) = to_location(r.0, r.1, &world, &line_index) { |
534 | changes.entry(loc.uri).or_insert(Vec::new()).push( | 528 | changes.entry(loc.uri).or_insert(Vec::new()).push(TextEdit { |
535 | TextEdit { | 529 | range: loc.range, |
536 | range: loc.range, | 530 | new_text: params.new_name.clone(), |
537 | new_text: params.new_name.clone() | 531 | }); |
538 | }); | ||
539 | } | 532 | } |
540 | } | 533 | } |
541 | 534 | ||
@@ -543,7 +536,7 @@ pub fn handle_rename( | |||
543 | changes: Some(changes), | 536 | changes: Some(changes), |
544 | 537 | ||
545 | // TODO: return this instead if client/server support it. See #144 | 538 | // TODO: return this instead if client/server support it. See #144 |
546 | document_changes : None, | 539 | document_changes: None, |
547 | })) | 540 | })) |
548 | } | 541 | } |
549 | 542 | ||
@@ -557,9 +550,11 @@ pub fn handle_references( | |||
557 | 550 | ||
558 | let refs = world.analysis().find_all_refs(file_id, offset)?; | 551 | let refs = world.analysis().find_all_refs(file_id, offset)?; |
559 | 552 | ||
560 | Ok(Some(refs.into_iter() | 553 | Ok(Some( |
561 | .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()) | 554 | refs.into_iter() |
562 | .collect())) | 555 | .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()) |
556 | .collect(), | ||
557 | )) | ||
563 | } | 558 | } |
564 | 559 | ||
565 | pub fn handle_code_action( | 560 | pub fn handle_code_action( |
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index 9ddc3fd0b..c568706bd 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs | |||
@@ -24,7 +24,10 @@ use crate::{ | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | #[derive(Debug, Fail)] | 26 | #[derive(Debug, Fail)] |
27 | #[fail(display = "Language Server request failed with {}. ({})", code, message)] | 27 | #[fail( |
28 | display = "Language Server request failed with {}. ({})", | ||
29 | code, message | ||
30 | )] | ||
28 | pub struct LspError { | 31 | pub struct LspError { |
29 | pub code: i32, | 32 | pub code: i32, |
30 | pub message: String, | 33 | pub message: String, |
@@ -32,7 +35,7 @@ pub struct LspError { | |||
32 | 35 | ||
33 | impl LspError { | 36 | impl LspError { |
34 | pub fn new(code: i32, message: String) -> LspError { | 37 | pub fn new(code: i32, message: String) -> LspError { |
35 | LspError {code, message} | 38 | LspError { code, message } |
36 | } | 39 | } |
37 | } | 40 | } |
38 | 41 | ||
@@ -214,11 +217,7 @@ fn main_loop_inner( | |||
214 | } | 217 | } |
215 | } | 218 | } |
216 | 219 | ||
217 | fn on_task( | 220 | fn on_task(task: Task, msg_sender: &Sender<RawMessage>, pending_requests: &mut FxHashSet<u64>) { |
218 | task: Task, | ||
219 | msg_sender: &Sender<RawMessage>, | ||
220 | pending_requests: &mut FxHashSet<u64>, | ||
221 | ) { | ||
222 | match task { | 221 | match task { |
223 | Task::Respond(response) => { | 222 | Task::Respond(response) => { |
224 | if pending_requests.remove(&response.id) { | 223 | if pending_requests.remove(&response.id) { |
@@ -373,12 +372,16 @@ impl<'a> PoolDispatcher<'a> { | |||
373 | self.pool.spawn(move || { | 372 | self.pool.spawn(move || { |
374 | let resp = match f(world, params) { | 373 | let resp = match f(world, params) { |
375 | Ok(resp) => RawResponse::ok::<R>(id, &resp), | 374 | Ok(resp) => RawResponse::ok::<R>(id, &resp), |
376 | Err(e) => { | 375 | Err(e) => match e.downcast::<LspError>() { |
377 | match e.downcast::<LspError>() { | 376 | Ok(lsp_error) => { |
378 | Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message), | 377 | RawResponse::err(id, lsp_error.code, lsp_error.message) |
379 | Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, format!("{}\n{}", e, e.backtrace())) | ||
380 | } | 378 | } |
381 | } | 379 | Err(e) => RawResponse::err( |
380 | id, | ||
381 | ErrorCode::InternalError as i32, | ||
382 | format!("{}\n{}", e, e.backtrace()), | ||
383 | ), | ||
384 | }, | ||
382 | }; | 385 | }; |
383 | let task = Task::Respond(resp); | 386 | let task = Task::Respond(resp); |
384 | sender.send(task); | 387 | sender.send(task); |
@@ -412,7 +415,7 @@ fn update_file_notifications_on_threadpool( | |||
412 | if !is_canceled(&e) { | 415 | if !is_canceled(&e) { |
413 | error!("failed to compute diagnostics: {:?}", e); | 416 | error!("failed to compute diagnostics: {:?}", e); |
414 | } | 417 | } |
415 | }, | 418 | } |
416 | Ok(params) => { | 419 | Ok(params) => { |
417 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); | 420 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); |
418 | sender.send(Task::Notify(not)); | 421 | sender.send(Task::Notify(not)); |
@@ -423,7 +426,7 @@ fn update_file_notifications_on_threadpool( | |||
423 | if !is_canceled(&e) { | 426 | if !is_canceled(&e) { |
424 | error!("failed to compute decorations: {:?}", e); | 427 | error!("failed to compute decorations: {:?}", e); |
425 | } | 428 | } |
426 | }, | 429 | } |
427 | Ok(params) => { | 430 | Ok(params) => { |
428 | let not = RawNotification::new::<req::PublishDecorations>(¶ms); | 431 | let not = RawNotification::new::<req::PublishDecorations>(¶ms); |
429 | sender.send(Task::Notify(not)) | 432 | sender.send(Task::Notify(not)) |
diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index d5957d673..dd09fa10a 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs | |||
@@ -33,7 +33,8 @@ impl PathMap { | |||
33 | } | 33 | } |
34 | pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> (bool, FileId) { | 34 | pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> (bool, FileId) { |
35 | let mut inserted = false; | 35 | let mut inserted = false; |
36 | let file_id = self.path2id | 36 | let file_id = self |
37 | .path2id | ||
37 | .get(path.as_path()) | 38 | .get(path.as_path()) |
38 | .map(|&id| id) | 39 | .map(|&id| id) |
39 | .unwrap_or_else(|| { | 40 | .unwrap_or_else(|| { |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 6cd04d84c..9d911912d 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -6,8 +6,8 @@ pub use languageserver_types::{ | |||
6 | notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CompletionParams, | 6 | notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CompletionParams, |
7 | CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, | 7 | CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, |
8 | DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, | 8 | DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, |
9 | PublishDiagnosticsParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, | 9 | PublishDiagnosticsParams, ReferenceParams, SignatureHelp, TextDocumentEdit, |
10 | TextEdit, WorkspaceSymbolParams, ReferenceParams, | 10 | TextDocumentPositionParams, TextEdit, WorkspaceSymbolParams, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | pub enum SyntaxTree {} | 13 | pub enum SyntaxTree {} |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 25986e230..3e76d2527 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -5,7 +5,9 @@ use std::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use languageserver_types::Url; | 7 | use languageserver_types::Url; |
8 | use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, FileId, FileResolver, LibraryData}; | 8 | use ra_analysis::{ |
9 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FileResolver, LibraryData, | ||
10 | }; | ||
9 | use rustc_hash::FxHashMap; | 11 | use rustc_hash::FxHashMap; |
10 | 12 | ||
11 | use crate::{ | 13 | use crate::{ |
@@ -65,9 +67,7 @@ impl ServerWorldState { | |||
65 | Some((file_id, text)) | 67 | Some((file_id, text)) |
66 | } | 68 | } |
67 | }) | 69 | }) |
68 | .for_each(|(file_id, text)| { | 70 | .for_each(|(file_id, text)| change.add_file(file_id, text)); |
69 | change.add_file(file_id, text) | ||
70 | }); | ||
71 | } | 71 | } |
72 | if inserted { | 72 | if inserted { |
73 | change.set_file_resolver(Arc::new(self.path_map.clone())) | 73 | change.set_file_resolver(Arc::new(self.path_map.clone())) |
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs index f92529d3e..faf5a6211 100644 --- a/crates/ra_syntax/src/algo/mod.rs +++ b/crates/ra_syntax/src/algo/mod.rs | |||
@@ -1,10 +1,7 @@ | |||
1 | pub mod visit; | 1 | pub mod visit; |
2 | // pub mod walk; | 2 | // pub mod walk; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{text_utils::contains_offset_nonstrict, SyntaxNodeRef, TextRange, TextUnit}; |
5 | text_utils::{contains_offset_nonstrict}, | ||
6 | SyntaxNodeRef, TextRange, TextUnit, | ||
7 | }; | ||
8 | 5 | ||
9 | pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { | 6 | pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { |
10 | let range = node.range(); | 7 | let range = node.range(); |
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs index 3aa11b9dd..688ffff47 100644 --- a/crates/ra_syntax/src/ast/mod.rs +++ b/crates/ra_syntax/src/ast/mod.rs | |||
@@ -66,7 +66,9 @@ pub trait AttrsOwner<'a>: AstNode<'a> { | |||
66 | } | 66 | } |
67 | 67 | ||
68 | pub trait DocCommentsOwner<'a>: AstNode<'a> { | 68 | pub trait DocCommentsOwner<'a>: AstNode<'a> { |
69 | fn doc_comments(self) -> AstChildren<'a, Comment<'a>> { children(self) } | 69 | fn doc_comments(self) -> AstChildren<'a, Comment<'a>> { |
70 | children(self) | ||
71 | } | ||
70 | 72 | ||
71 | /// Returns the textual content of a doc comment block as a single string. | 73 | /// Returns the textual content of a doc comment block as a single string. |
72 | /// That is, strips leading `///` and joins lines | 74 | /// That is, strips leading `///` and joins lines |
@@ -74,12 +76,15 @@ pub trait DocCommentsOwner<'a>: AstNode<'a> { | |||
74 | self.doc_comments() | 76 | self.doc_comments() |
75 | .map(|comment| { | 77 | .map(|comment| { |
76 | let prefix = comment.prefix(); | 78 | let prefix = comment.prefix(); |
77 | let trimmed = comment.text().as_str() | 79 | let trimmed = comment |
80 | .text() | ||
81 | .as_str() | ||
78 | .trim() | 82 | .trim() |
79 | .trim_start_matches(prefix) | 83 | .trim_start_matches(prefix) |
80 | .trim_start(); | 84 | .trim_start(); |
81 | trimmed.to_owned() | 85 | trimmed.to_owned() |
82 | }).join("\n") | 86 | }) |
87 | .join("\n") | ||
83 | } | 88 | } |
84 | } | 89 | } |
85 | 90 | ||
@@ -250,7 +255,6 @@ impl<'a> IfExpr<'a> { | |||
250 | } | 255 | } |
251 | } | 256 | } |
252 | 257 | ||
253 | |||
254 | #[derive(Debug, Clone, Copy)] | 258 | #[derive(Debug, Clone, Copy)] |
255 | pub enum PathSegmentKind<'a> { | 259 | pub enum PathSegmentKind<'a> { |
256 | Name(NameRef<'a>), | 260 | Name(NameRef<'a>), |
@@ -261,7 +265,9 @@ pub enum PathSegmentKind<'a> { | |||
261 | 265 | ||
262 | impl<'a> PathSegment<'a> { | 266 | impl<'a> PathSegment<'a> { |
263 | pub fn parent_path(self) -> Path<'a> { | 267 | pub fn parent_path(self) -> Path<'a> { |
264 | self.syntax().parent().and_then(Path::cast) | 268 | self.syntax() |
269 | .parent() | ||
270 | .and_then(Path::cast) | ||
265 | .expect("segments are always nested in paths") | 271 | .expect("segments are always nested in paths") |
266 | } | 272 | } |
267 | 273 | ||
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 3698eccd7..79394fd53 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -52,7 +52,9 @@ pub use crate::{ | |||
52 | reparsing::AtomEdit, | 52 | reparsing::AtomEdit, |
53 | rowan::{SmolStr, TextRange, TextUnit}, | 53 | rowan::{SmolStr, TextRange, TextUnit}, |
54 | syntax_kinds::SyntaxKind, | 54 | syntax_kinds::SyntaxKind, |
55 | yellow::{Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent}, | 55 | yellow::{ |
56 | Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent, | ||
57 | }, | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | use crate::yellow::GreenNode; | 60 | use crate::yellow::GreenNode; |
diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index 8ee02724d..00f00139a 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs | |||
@@ -1,6 +1,4 @@ | |||
1 | use crate::{ | 1 | use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent}; |
2 | File, SyntaxKind, SyntaxNodeRef, WalkEvent | ||
3 | }; | ||
4 | use std::fmt::Write; | 2 | use std::fmt::Write; |
5 | 3 | ||
6 | /// Parse a file and create a string representation of the resulting parse tree. | 4 | /// Parse a file and create a string representation of the resulting parse tree. |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 8980f077f..d9fbb9b5b 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -89,7 +89,6 @@ pub fn add_cursor(text: &str, offset: TextUnit) -> String { | |||
89 | res | 89 | res |
90 | } | 90 | } |
91 | 91 | ||
92 | |||
93 | #[derive(Debug)] | 92 | #[derive(Debug)] |
94 | pub struct FixtureEntry { | 93 | pub struct FixtureEntry { |
95 | pub meta: String, | 94 | pub meta: String, |
@@ -112,25 +111,29 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { | |||
112 | macro_rules! flush { | 111 | macro_rules! flush { |
113 | () => { | 112 | () => { |
114 | if let Some(meta) = meta { | 113 | if let Some(meta) = meta { |
115 | res.push(FixtureEntry { meta: meta.to_string(), text: buf.clone() }); | 114 | res.push(FixtureEntry { |
115 | meta: meta.to_string(), | ||
116 | text: buf.clone(), | ||
117 | }); | ||
116 | buf.clear(); | 118 | buf.clear(); |
117 | } | 119 | } |
118 | }; | 120 | }; |
119 | }; | 121 | }; |
120 | let margin = fixture.lines() | 122 | let margin = fixture |
123 | .lines() | ||
121 | .filter(|it| it.trim_start().starts_with("//-")) | 124 | .filter(|it| it.trim_start().starts_with("//-")) |
122 | .map(|it| it.len() - it.trim_start().len()) | 125 | .map(|it| it.len() - it.trim_start().len()) |
123 | .next().expect("empty fixture"); | 126 | .next() |
124 | let lines = fixture.lines() | 127 | .expect("empty fixture"); |
125 | .filter_map(|line| { | 128 | let lines = fixture.lines().filter_map(|line| { |
126 | if line.len() >= margin { | 129 | if line.len() >= margin { |
127 | assert!(line[..margin].trim().is_empty()); | 130 | assert!(line[..margin].trim().is_empty()); |
128 | Some(&line[margin..]) | 131 | Some(&line[margin..]) |
129 | } else { | 132 | } else { |
130 | assert!(line.trim().is_empty()); | 133 | assert!(line.trim().is_empty()); |
131 | None | 134 | None |
132 | } | 135 | } |
133 | }); | 136 | }); |
134 | 137 | ||
135 | for line in lines { | 138 | for line in lines { |
136 | if line.starts_with("//-") { | 139 | if line.starts_with("//-") { |
diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 29c46c7c4..3387d0620 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | extern crate itertools; | ||
2 | extern crate failure; | 1 | extern crate failure; |
2 | extern crate itertools; | ||
3 | extern crate teraron; | 3 | extern crate teraron; |
4 | 4 | ||
5 | use std::{ | 5 | use std::{ |
@@ -7,10 +7,10 @@ use std::{ | |||
7 | process::Command, | 7 | process::Command, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use itertools::Itertools; | ||
11 | use failure::bail; | 10 | use failure::bail; |
11 | use itertools::Itertools; | ||
12 | 12 | ||
13 | pub use teraron::{Mode, Verify, Overwrite}; | 13 | pub use teraron::{Mode, Overwrite, Verify}; |
14 | 14 | ||
15 | pub type Result<T> = ::std::result::Result<T, failure::Error>; | 15 | pub type Result<T> = ::std::result::Result<T, failure::Error>; |
16 | 16 | ||
@@ -63,16 +63,8 @@ pub fn generate(mode: Mode) -> Result<()> { | |||
63 | let grammar = project_root().join(GRAMMAR); | 63 | let grammar = project_root().join(GRAMMAR); |
64 | let syntax_kinds = project_root().join(SYNTAX_KINDS); | 64 | let syntax_kinds = project_root().join(SYNTAX_KINDS); |
65 | let ast = project_root().join(AST); | 65 | let ast = project_root().join(AST); |
66 | teraron::generate( | 66 | teraron::generate(&syntax_kinds, &grammar, mode)?; |
67 | &syntax_kinds, | 67 | teraron::generate(&ast, &grammar, mode)?; |
68 | &grammar, | ||
69 | mode, | ||
70 | )?; | ||
71 | teraron::generate( | ||
72 | &ast, | ||
73 | &grammar, | ||
74 | mode, | ||
75 | )?; | ||
76 | Ok(()) | 68 | Ok(()) |
77 | } | 69 | } |
78 | 70 | ||
@@ -101,9 +93,18 @@ pub fn run(cmdline: &str, dir: &str) -> Result<()> { | |||
101 | 93 | ||
102 | pub fn run_rustfmt(mode: Mode) -> Result<()> { | 94 | pub fn run_rustfmt(mode: Mode) -> Result<()> { |
103 | run(&format!("rustup install {}", TOOLCHAIN), ".")?; | 95 | run(&format!("rustup install {}", TOOLCHAIN), ".")?; |
104 | run(&format!("rustup component add rustfmt-preview --toolchain {}", TOOLCHAIN), ".")?; | 96 | run( |
97 | &format!( | ||
98 | "rustup component add rustfmt-preview --toolchain {}", | ||
99 | TOOLCHAIN | ||
100 | ), | ||
101 | ".", | ||
102 | )?; | ||
105 | if mode == Verify { | 103 | if mode == Verify { |
106 | run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?; | 104 | run( |
105 | &format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), | ||
106 | ".", | ||
107 | )?; | ||
107 | } else { | 108 | } else { |
108 | run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?; | 109 | run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?; |
109 | } | 110 | } |
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs index 91675bbf0..dc623a464 100644 --- a/crates/tools/src/main.rs +++ b/crates/tools/src/main.rs | |||
@@ -1,19 +1,17 @@ | |||
1 | extern crate clap; | 1 | extern crate clap; |
2 | extern crate failure; | 2 | extern crate failure; |
3 | extern crate teraron; | ||
3 | extern crate tools; | 4 | extern crate tools; |
4 | extern crate walkdir; | 5 | extern crate walkdir; |
5 | extern crate teraron; | ||
6 | 6 | ||
7 | use clap::{App, Arg, SubCommand}; | 7 | use clap::{App, Arg, SubCommand}; |
8 | use failure::bail; | ||
8 | use std::{ | 9 | use std::{ |
9 | collections::HashMap, | 10 | collections::HashMap, |
10 | fs, | 11 | fs, |
11 | path::{Path, PathBuf}, | 12 | path::{Path, PathBuf}, |
12 | }; | 13 | }; |
13 | use tools::{ | 14 | use tools::{collect_tests, generate, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify}; |
14 | collect_tests, Result, Test, generate, Mode, Overwrite, Verify, run, run_rustfmt, | ||
15 | }; | ||
16 | use failure::bail; | ||
17 | 15 | ||
18 | const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; | 16 | const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; |
19 | const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline"; | 17 | const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline"; |
diff --git a/crates/tools/tests/cli.rs b/crates/tools/tests/cli.rs index 8c53a8230..2d238d9ea 100644 --- a/crates/tools/tests/cli.rs +++ b/crates/tools/tests/cli.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | extern crate tools; | 1 | extern crate tools; |
2 | 2 | ||
3 | use tools::{ | 3 | use tools::{generate, run_rustfmt, Verify}; |
4 | generate, Verify, run_rustfmt, | ||
5 | }; | ||
6 | 4 | ||
7 | #[test] | 5 | #[test] |
8 | fn verify_template_generation() { | 6 | fn verify_template_generation() { |
@@ -14,6 +12,9 @@ fn verify_template_generation() { | |||
14 | #[test] | 12 | #[test] |
15 | fn check_code_formatting() { | 13 | fn check_code_formatting() { |
16 | if let Err(error) = run_rustfmt(Verify) { | 14 | if let Err(error) = run_rustfmt(Verify) { |
17 | panic!("{}. Please format the code by running `cargo format`", error); | 15 | panic!( |
16 | "{}. Please format the code by running `cargo format`", | ||
17 | error | ||
18 | ); | ||
18 | } | 19 | } |
19 | } | 20 | } |