aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/completion.rs57
-rw-r--r--crates/ra_analysis/src/db.rs13
-rw-r--r--crates/ra_analysis/src/descriptors/function/imp.rs12
-rw-r--r--crates/ra_analysis/src/descriptors/function/mod.rs29
-rw-r--r--crates/ra_analysis/src/descriptors/function/scope.rs7
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs39
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs33
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs30
-rw-r--r--crates/ra_analysis/src/descriptors/module/scope.rs5
-rw-r--r--crates/ra_analysis/src/imp.rs77
-rw-r--r--crates/ra_analysis/src/input.rs9
-rw-r--r--crates/ra_analysis/src/lib.rs47
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs17
-rw-r--r--crates/ra_analysis/src/symbol_index.rs5
-rw-r--r--crates/ra_analysis/src/syntax_ptr.rs23
-rw-r--r--crates/ra_analysis/tests/tests.rs105
-rw-r--r--crates/ra_editor/src/folding_ranges.rs12
-rw-r--r--crates/ra_editor/src/lib.rs2
-rw-r--r--crates/ra_editor/src/symbols.rs10
-rw-r--r--crates/ra_lsp_server/src/caps.rs10
-rw-r--r--crates/ra_lsp_server/src/conv.rs3
-rw-r--r--crates/ra_lsp_server/src/lib.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs87
-rw-r--r--crates/ra_lsp_server/src/main_loop/mod.rs31
-rw-r--r--crates/ra_lsp_server/src/path_map.rs3
-rw-r--r--crates/ra_lsp_server/src/req.rs4
-rw-r--r--crates/ra_lsp_server/src/server_world.rs8
-rw-r--r--crates/ra_syntax/src/algo/mod.rs5
-rw-r--r--crates/ra_syntax/src/ast/mod.rs16
-rw-r--r--crates/ra_syntax/src/lib.rs4
-rw-r--r--crates/ra_syntax/src/utils.rs4
-rw-r--r--crates/test_utils/src/lib.rs31
-rw-r--r--crates/tools/src/lib.rs31
-rw-r--r--crates/tools/src/main.rs8
-rw-r--r--crates/tools/tests/cli.rs9
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 @@
1use rustc_hash::{FxHashMap, FxHashSet}; 1use ra_editor::find_node_at_offset;
2use ra_editor::{find_node_at_offset};
3use ra_syntax::{ 2use 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};
9use rustc_hash::{FxHashMap, FxHashSet};
9 10
10use crate::{ 11use 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)]
21pub struct CompletionItem { 21pub 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
30pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, offset: TextUnit) -> Cancelable<Option<Vec<CompletionItem>>> { 30pub(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 63pub(crate) fn find_target_module(
60 64 module_tree: &ModuleTree,
61pub(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
73fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> { 80fn 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
93pub(crate) fn scope_completion( 100pub(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
161fn complete_name_ref( 168fn 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)]
370mod tests { 377mod 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 @@
1use std::{ 1use std::sync::Arc;
2 sync::Arc,
3};
4 2
5use ra_editor::LineIndex; 3use ra_editor::LineIndex;
6use ra_syntax::File; 4use ra_syntax::File;
@@ -8,14 +6,13 @@ use salsa;
8 6
9use crate::{ 7use 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::ast::{AstNode, FnDef, FnDefNode};
4 ast::{AstNode, FnDef, FnDefNode},
5};
6 4
7use crate::{ 5use 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 @@
1pub(super) mod imp; 1pub(super) mod imp;
2mod scope; 2mod scope;
3 3
4use std::cmp::{min, max}; 4use std::cmp::{max, min};
5 5
6use ra_syntax::{ 6use ra_syntax::{
7 ast::{self, AstNode, DocCommentsOwner, NameOwner}, 7 ast::{self, AstNode, DocCommentsOwner, NameOwner},
8 TextRange, TextUnit 8 TextRange, TextUnit,
9}; 9};
10 10
11use crate::{ 11use crate::{syntax_ptr::SyntaxPtr, FileId};
12 FileId,
13 syntax_ptr::SyntaxPtr
14};
15
16pub(crate) use self::scope::{FnScopes, resolve_local_name};
17 12
13pub(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)]
20pub(crate) struct FnId(SyntaxPtr); 16pub(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)]
31pub struct FnDescriptor { 26pub 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
39impl FnDescriptor { 34impl 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)]
275mod tests { 273mod 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 @@
1pub(crate) mod module;
2pub(crate) mod function; 1pub(crate) mod function;
2pub(crate) mod module;
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use ra_syntax::{ 6use ra_syntax::{
7 SmolStr,
8 ast::{self, AstNode, FnDefNode}, 7 ast::{self, AstNode, FnDefNode},
9 TextRange 8 SmolStr, TextRange,
10}; 9};
11 10
12use crate::{ 11use 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
22salsa::query_group! { 20salsa::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)]
50pub struct ReferenceDescriptor { 48pub 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)]
56pub struct DeclarationDescriptor<'a> { 54pub 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
61impl<'a> DeclarationDescriptor<'a> { 59impl<'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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf;
4use rustc_hash::{FxHashMap, FxHashSet};
5use ra_syntax::{ 3use ra_syntax::{
6 SmolStr,
7 ast::{self, NameOwner}, 4 ast::{self, NameOwner},
5 SmolStr,
8}; 6};
7use relative_path::RelativePathBuf;
8use rustc_hash::{FxHashMap, FxHashSet};
9 9
10use crate::{ 10use 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
16use super::{ 17use super::{LinkData, LinkId, ModuleData, ModuleId, ModuleScope, ModuleTree, Problem};
17 ModuleData, ModuleTree, ModuleId, LinkId, LinkData, Problem, ModuleScope
18};
19
20 18
21pub(crate) fn submodules(db: &impl DescriptorDatabase, file_id: FileId) -> Cancelable<Arc<Vec<SmolStr>>> { 19pub(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)]
62pub struct Submodule { 62pub struct Submodule {
63 pub name: SmolStr, 63 pub name: SmolStr,
64} 64}
65 65
66
67fn create_module_tree<'a>( 66fn 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 @@
1pub(super) mod imp; 1pub(super) mod imp;
2pub(crate) mod scope; 2pub(crate) mod scope;
3 3
4use ra_syntax::{
5 ast::{self, AstNode, NameOwner},
6 SmolStr, SyntaxNode,
7};
4use relative_path::RelativePathBuf; 8use relative_path::RelativePathBuf;
5use ra_syntax::{ast::{self, NameOwner, AstNode}, SmolStr, SyntaxNode};
6 9
7use crate::FileId; 10use crate::FileId;
8 11
@@ -16,9 +19,11 @@ pub(crate) struct ModuleTree {
16 19
17impl ModuleTree { 20impl 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
129impl ModuleTree { 126impl 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
4use ra_syntax::{ 3use ra_syntax::{
5 ast::{self, ModuleItemOwner}, 4 ast::{self, ModuleItemOwner},
6 File, AstNode, SmolStr, 5 AstNode, File, SmolStr,
7}; 6};
8 7
9use crate::syntax_ptr::LocalSyntaxPtr; 8use crate::syntax_ptr::LocalSyntaxPtr;
@@ -103,7 +102,7 @@ fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
103#[cfg(test)] 102#[cfg(test)]
104mod tests { 103mod 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::{
13use rayon::prelude::*; 13use rayon::prelude::*;
14use relative_path::RelativePath; 14use relative_path::RelativePath;
15use rustc_hash::FxHashSet; 15use rustc_hash::FxHashSet;
16use salsa::{ParallelDatabase, Database}; 16use salsa::{Database, ParallelDatabase};
17 17
18use crate::{ 18use 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
98impl AnalysisHostImpl { 94impl 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 @@
1use std::{ 1use std::{fmt, sync::Arc};
2 sync::Arc,
3 fmt,
4};
5 2
6use salsa;
7use rustc_hash::FxHashSet;
8use relative_path::RelativePath; 3use relative_path::RelativePath;
9use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
5use rustc_hash::FxHashSet;
6use salsa;
10 7
11use crate::{symbol_index::SymbolIndex, FileResolverImp}; 8use 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;
6extern crate rustc_hash; 6extern crate rustc_hash;
7extern crate salsa; 7extern crate salsa;
8 8
9mod input; 9mod completion;
10mod db; 10mod db;
11mod descriptors; 11mod descriptors;
12mod imp; 12mod imp;
13mod input;
14pub mod mock_analysis;
13mod symbol_index; 15mod symbol_index;
14mod completion;
15mod syntax_ptr; 16mod syntax_ptr;
16pub mod mock_analysis;
17 17
18use std::{ 18use std::{fmt, sync::Arc};
19 fmt,
20 sync::Arc,
21};
22 19
23use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; 20use ra_syntax::{AtomEdit, File, TextRange, TextUnit};
24use relative_path::RelativePathBuf;
25use rayon::prelude::*; 21use rayon::prelude::*;
22use relative_path::RelativePathBuf;
26 23
27use crate::{ 24use crate::{
28 imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}, 25 imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
@@ -30,13 +27,12 @@ use crate::{
30}; 27};
31 28
32pub use crate::{ 29pub 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};
37pub use ra_editor::{ 34pub 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
53impl std::error::Error for Canceled { 49impl std::error::Error for Canceled {}
54}
55 50
56#[derive(Default)] 51#[derive(Default)]
57pub struct AnalysisChange { 52pub struct AnalysisChange {
@@ -76,7 +71,6 @@ impl fmt::Debug for AnalysisChange {
76 } 71 }
77} 72}
78 73
79
80impl AnalysisChange { 74impl 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
2use std::sync::Arc; 1use std::sync::Arc;
3 2
4use relative_path::{RelativePath, RelativePathBuf};
5use ra_syntax::TextUnit; 3use ra_syntax::TextUnit;
4use relative_path::{RelativePath, RelativePathBuf};
6use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; 5use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
7 6
8use crate::{ 7use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FileResolver};
9 AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver,
10};
11 8
12#[derive(Debug)] 9#[derive(Debug)]
13pub struct FilePosition { 10pub 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
59impl Query { 59impl 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 @@
1use std::marker::PhantomData; 1use std::marker::PhantomData;
2 2
3use ra_syntax::{ 3use 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
8use crate::FileId;
9use crate::db::SyntaxDatabase; 8use crate::db::SyntaxDatabase;
9use crate::FileId;
10 10
11salsa::query_group! { 11salsa::query_group! {
12 pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase { 12 pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase {
@@ -52,12 +52,10 @@ trait ToAst {
52impl<'a> ToAst for &'a OwnedAst<ast::FnDef<'static>> { 52impl<'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)]
63pub(crate) struct LocalSyntaxPtr { 61pub(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]
95fn test_local_syntax_ptr() { 96fn 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;
5extern crate rustc_hash; 5extern crate rustc_hash;
6extern crate test_utils; 6extern crate test_utils;
7 7
8use ra_syntax::{TextRange}; 8use ra_syntax::TextRange;
9use test_utils::{assert_eq_dbg}; 9use test_utils::assert_eq_dbg;
10 10
11use ra_analysis::{ 11use 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
16fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) { 16fn 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]
22fn test_resolve_module() { 25fn 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]
75fn test_resolve_parent_module() { 86fn 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]
90fn test_resolve_crate_root() { 103fn 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!(
249r#"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.
254let five = 5; 271let five = 5;
255 272
256assert_eq!(6, my_crate::add_one(5)); 273assert_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 {
280pub fn do_it() { 300pub 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!(
291r#"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.
296let five = 5; 319let five = 5;
297 320
298assert_eq!(6, my_crate::add_one(5)); 321assert_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!(
339r#"Method is called when writer finishes. 369 desc.doc,
340 370 Some(
341By default this method stops actor's `Context`."#.into())); 371 r#"Method is called when writer finishes.
372
373By default this method stops actor's `Context`."#
374 .into()
375 )
376 );
342} 377}
343 378
344
345fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> { 379fn 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]
392fn test_complete_crate_path() { 428fn 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)]
154mod tests { 152mod 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 @@
1use crate::TextRange; 1use crate::TextRange;
2 2
3use ra_syntax::{ 3use 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 @@
1use languageserver_types::{ 1use 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
8pub fn server_capabilities() -> ServerCapabilities { 8pub 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;
36mod vfs; 36mod vfs;
37 37
38pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 38pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
39pub use crate::{caps::server_capabilities, main_loop::main_loop, main_loop::LspError}; \ No newline at end of file 39pub 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 @@
1use std::collections::HashMap; 1use std::collections::HashMap;
2 2
3use rustc_hash::FxHashMap; 3use gen_lsp_server::ErrorCode;
4use languageserver_types::{ 4use 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};
10use gen_lsp_server::ErrorCode;
11use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; 11use ra_analysis::{FileId, FoldKind, Query, RunnableKind};
12use ra_syntax::text_utils::contains_offset_nonstrict; 12use ra_syntax::text_utils::contains_offset_nonstrict;
13use rustc_hash::FxHashMap;
13use serde_json::to_value; 14use serde_json::to_value;
14 15
15use crate::{ 16use 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
23pub fn handle_syntax_tree( 24pub 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
514pub fn handle_rename( 507pub 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
565pub fn handle_code_action( 560pub 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)]
28pub struct LspError { 31pub 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
33impl LspError { 36impl 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
217fn on_task( 220fn 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>(&params); 420 let not = RawNotification::new::<req::PublishDiagnostics>(&params);
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>(&params); 431 let not = RawNotification::new::<req::PublishDecorations>(&params);
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
13pub enum SyntaxTree {} 13pub 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
7use languageserver_types::Url; 7use languageserver_types::Url;
8use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, FileId, FileResolver, LibraryData}; 8use ra_analysis::{
9 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FileResolver, LibraryData,
10};
9use rustc_hash::FxHashMap; 11use rustc_hash::FxHashMap;
10 12
11use crate::{ 13use 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 @@
1pub mod visit; 1pub mod visit;
2// pub mod walk; 2// pub mod walk;
3 3
4use crate::{ 4use crate::{text_utils::contains_offset_nonstrict, SyntaxNodeRef, TextRange, TextUnit};
5 text_utils::{contains_offset_nonstrict},
6 SyntaxNodeRef, TextRange, TextUnit,
7};
8 5
9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { 6pub 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
68pub trait DocCommentsOwner<'a>: AstNode<'a> { 68pub 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)]
255pub enum PathSegmentKind<'a> { 259pub enum PathSegmentKind<'a> {
256 Name(NameRef<'a>), 260 Name(NameRef<'a>),
@@ -261,7 +265,9 @@ pub enum PathSegmentKind<'a> {
261 265
262impl<'a> PathSegment<'a> { 266impl<'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
58use crate::yellow::GreenNode; 60use 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 @@
1use crate::{ 1use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent};
2 File, SyntaxKind, SyntaxNodeRef, WalkEvent
3};
4use std::fmt::Write; 2use 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)]
94pub struct FixtureEntry { 93pub 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 @@
1extern crate itertools;
2extern crate failure; 1extern crate failure;
2extern crate itertools;
3extern crate teraron; 3extern crate teraron;
4 4
5use std::{ 5use std::{
@@ -7,10 +7,10 @@ use std::{
7 process::Command, 7 process::Command,
8}; 8};
9 9
10use itertools::Itertools;
11use failure::bail; 10use failure::bail;
11use itertools::Itertools;
12 12
13pub use teraron::{Mode, Verify, Overwrite}; 13pub use teraron::{Mode, Overwrite, Verify};
14 14
15pub type Result<T> = ::std::result::Result<T, failure::Error>; 15pub 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
102pub fn run_rustfmt(mode: Mode) -> Result<()> { 94pub 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 @@
1extern crate clap; 1extern crate clap;
2extern crate failure; 2extern crate failure;
3extern crate teraron;
3extern crate tools; 4extern crate tools;
4extern crate walkdir; 5extern crate walkdir;
5extern crate teraron;
6 6
7use clap::{App, Arg, SubCommand}; 7use clap::{App, Arg, SubCommand};
8use failure::bail;
8use std::{ 9use std::{
9 collections::HashMap, 10 collections::HashMap,
10 fs, 11 fs,
11 path::{Path, PathBuf}, 12 path::{Path, PathBuf},
12}; 13};
13use tools::{ 14use 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};
16use failure::bail;
17 15
18const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; 16const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar";
19const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline"; 17const 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 @@
1extern crate tools; 1extern crate tools;
2 2
3use tools::{ 3use tools::{generate, run_rustfmt, Verify};
4 generate, Verify, run_rustfmt,
5};
6 4
7#[test] 5#[test]
8fn verify_template_generation() { 6fn verify_template_generation() {
@@ -14,6 +12,9 @@ fn verify_template_generation() {
14#[test] 12#[test]
15fn check_code_formatting() { 13fn 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}