aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_db/src/lib.rs1
-rw-r--r--crates/ra_db/src/mock.rs30
-rw-r--r--crates/ra_hir/src/code_model_api.rs30
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs4
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs13
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs15
-rw-r--r--crates/ra_hir/src/db.rs25
-rw-r--r--crates/ra_hir/src/expr.rs12
-rw-r--r--crates/ra_hir/src/expr/scope.rs (renamed from crates/ra_hir/src/code_model_impl/function/scope.rs)31
-rw-r--r--crates/ra_hir/src/impl_block.rs57
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/module_tree.rs17
-rw-r--r--crates/ra_hir/src/nameres.rs33
-rw-r--r--crates/ra_hir/src/nameres/tests.rs48
-rw-r--r--crates/ra_hir/src/query_definitions.rs42
-rw-r--r--crates/ra_hir/src/source_binder.rs29
-rw-r--r--crates/ra_hir/src/ty.rs196
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap23
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_array.snap14
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap24
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap46
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap10
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap26
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap37
-rw-r--r--crates/ra_hir/src/ty/tests.rs32
-rw-r--r--crates/ra_ide_api/Cargo.toml6
-rw-r--r--crates/ra_ide_api/src/call_info.rs66
-rw-r--r--crates/ra_ide_api/src/completion.rs19
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs38
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap32
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap8
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap32
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap28
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap14
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap14
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap14
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion1.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion2.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion3.snap16
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap28
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap32
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap32
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap30
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap26
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap38
-rw-r--r--crates/ra_ide_api/src/db.rs11
-rw-r--r--crates/ra_ide_api/src/imp.rs49
-rw-r--r--crates/ra_ide_api/src/impls.rs120
-rw-r--r--crates/ra_ide_api/src/lib.rs21
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs6
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs10
-rw-r--r--crates/ra_ide_api/src/status.rs53
-rw-r--r--crates/ra_ide_api/tests/test/main.rs12
-rw-r--r--crates/ra_ide_api_light/src/assists.rs8
-rw-r--r--crates/ra_ide_api_light/src/assists/introduce_variable.rs297
-rw-r--r--crates/ra_ide_api_light/src/test_utils.rs12
-rw-r--r--crates/ra_lsp_server/Cargo.toml3
-rw-r--r--crates/ra_lsp_server/src/caps.rs4
-rw-r--r--crates/ra_lsp_server/src/conv.rs19
-rw-r--r--crates/ra_lsp_server/src/lib.rs1
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs4
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs35
-rw-r--r--crates/ra_lsp_server/src/markdown.rs38
-rw-r--r--crates/ra_lsp_server/src/req.rs24
-rw-r--r--crates/ra_lsp_server/src/server_world.rs6
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/main.rs2
-rw-r--r--crates/ra_syntax/src/algo.rs4
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron2
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs18
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt83
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs5
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt47
85 files changed, 1656 insertions, 734 deletions
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 2d39b77ed..3bae22c74 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -5,8 +5,8 @@ version = "0.1.0"
5authors = ["Aleksey Kladov <[email protected]>"] 5authors = ["Aleksey Kladov <[email protected]>"]
6 6
7[dependencies] 7[dependencies]
8salsa = "0.10.0"
8relative-path = "0.4.0" 9relative-path = "0.4.0"
9salsa = "0.10.0-alpha5"
10rustc-hash = "1.0" 10rustc-hash = "1.0"
11parking_lot = "0.7.0" 11parking_lot = "0.7.0"
12 12
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 6e17f33f0..ca775030d 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -2,7 +2,6 @@
2mod cancellation; 2mod cancellation;
3mod input; 3mod input;
4mod loc2id; 4mod loc2id;
5pub mod mock;
6 5
7use std::{ 6use std::{
8 panic, sync::Arc, 7 panic, sync::Arc,
diff --git a/crates/ra_db/src/mock.rs b/crates/ra_db/src/mock.rs
deleted file mode 100644
index 5e185062b..000000000
--- a/crates/ra_db/src/mock.rs
+++ /dev/null
@@ -1,30 +0,0 @@
1use rustc_hash::FxHashSet;
2use relative_path::{RelativePath, RelativePathBuf};
3
4use crate::{FileId};
5
6#[derive(Default, Debug, Clone)]
7pub struct FileMap(Vec<(FileId, RelativePathBuf)>);
8
9impl FileMap {
10 pub fn add(&mut self, path: RelativePathBuf) -> FileId {
11 let file_id = FileId((self.0.len() + 1) as u32);
12 self.0.push((file_id, path));
13 file_id
14 }
15
16 pub fn files(&self) -> FxHashSet<FileId> {
17 self.iter().map(|(id, _)| id).collect()
18 }
19
20 pub fn file_id(&self, path: &str) -> FileId {
21 assert!(path.starts_with('/'));
22 self.iter().find(|(_, p)| p == &path[1..]).unwrap().0
23 }
24
25 fn iter<'a>(&'a self) -> impl Iterator<Item = (FileId, &'a RelativePath)> + 'a {
26 self.0
27 .iter()
28 .map(|(id, path)| (*id, path.as_relative_path()))
29 }
30}
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 191104890..9405aa8ad 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -10,12 +10,13 @@ use crate::{
10 nameres::{ModuleScope, lower::ImportId}, 10 nameres::{ModuleScope, lower::ImportId},
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::BodySyntaxMapping, 12 expr::BodySyntaxMapping,
13 ty::InferenceResult, 13 ty::{InferenceResult},
14 adt::{EnumVariantId, StructFieldId, VariantDef}, 14 adt::{EnumVariantId, StructFieldId, VariantDef},
15 generics::GenericParams, 15 generics::GenericParams,
16 docs::{Documentation, Docs, docs_from_ast}, 16 docs::{Documentation, Docs, docs_from_ast},
17 module_tree::ModuleId, 17 module_tree::ModuleId,
18 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, 18 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId},
19 impl_block::ImplId,
19}; 20};
20 21
21/// hir::Crate describes a single crate. It's the main interface with which 22/// hir::Crate describes a single crate. It's the main interface with which
@@ -51,7 +52,7 @@ pub enum Def {
51 52
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 53#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53pub struct Module { 54pub struct Module {
54 pub(crate) krate: CrateId, 55 pub(crate) krate: Crate,
55 pub(crate) module_id: ModuleId, 56 pub(crate) module_id: ModuleId,
56} 57}
57 58
@@ -126,9 +127,14 @@ impl Module {
126 self.import_source_impl(db, import) 127 self.import_source_impl(db, import)
127 } 128 }
128 129
130 /// Returns the syntax of the impl block in this module
131 pub fn impl_source(&self, db: &impl HirDatabase, impl_id: ImplId) -> TreeArc<ast::ImplBlock> {
132 self.impl_source_impl(db, impl_id)
133 }
134
129 /// Returns the crate this module is part of. 135 /// Returns the crate this module is part of.
130 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { 136 pub fn krate(&self, _db: &impl HirDatabase) -> Option<Crate> {
131 self.krate_impl(db) 137 Some(self.krate)
132 } 138 }
133 139
134 /// Topmost parent of this module. Every module has a `crate_root`, but some 140 /// Topmost parent of this module. Every module has a `crate_root`, but some
@@ -272,6 +278,10 @@ impl Struct {
272 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 278 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
273 db.generic_params((*self).into()) 279 db.generic_params((*self).into())
274 } 280 }
281
282 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
283 db.type_for_def((*self).into())
284 }
275} 285}
276 286
277impl Docs for Struct { 287impl Docs for Struct {
@@ -317,6 +327,10 @@ impl Enum {
317 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 327 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
318 db.generic_params((*self).into()) 328 db.generic_params((*self).into())
319 } 329 }
330
331 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
332 db.type_for_def((*self).into())
333 }
320} 334}
321 335
322impl Docs for Enum { 336impl Docs for Enum {
@@ -382,7 +396,7 @@ pub struct Function {
382 pub(crate) id: FunctionId, 396 pub(crate) id: FunctionId,
383} 397}
384 398
385pub use crate::code_model_impl::function::ScopeEntryWithSyntax; 399pub use crate::expr::ScopeEntryWithSyntax;
386 400
387/// The declared signature of a function. 401/// The declared signature of a function.
388#[derive(Debug, Clone, PartialEq, Eq)] 402#[derive(Debug, Clone, PartialEq, Eq)]
@@ -424,12 +438,16 @@ impl Function {
424 self.id.module(db) 438 self.id.module(db)
425 } 439 }
426 440
441 pub fn name(&self, db: &impl HirDatabase) -> Name {
442 self.signature(db).name.clone()
443 }
444
427 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { 445 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
428 db.body_syntax_mapping(*self) 446 db.body_syntax_mapping(*self)
429 } 447 }
430 448
431 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { 449 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
432 let scopes = db.fn_scopes(*self); 450 let scopes = db.expr_scopes(*self);
433 let syntax_mapping = db.body_syntax_mapping(*self); 451 let syntax_mapping = db.body_syntax_mapping(*self);
434 ScopesWithSyntaxMapping { 452 ScopesWithSyntaxMapping {
435 scopes, 453 scopes,
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index e0dd4d629..422643996 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -1,5 +1,3 @@
1mod scope;
2
3use std::sync::Arc; 1use std::sync::Arc;
4 2
5use ra_syntax::ast::{self, NameOwner}; 3use ra_syntax::ast::{self, NameOwner};
@@ -11,8 +9,6 @@ use crate::{
11 impl_block::ImplBlock, 9 impl_block::ImplBlock,
12}; 10};
13 11
14pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
15
16impl Function { 12impl Function {
17 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 13 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
18 db.body_hir(*self) 14 db.body_hir(*self)
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs
index cdd30b402..86f29d959 100644
--- a/crates/ra_hir/src/code_model_impl/krate.rs
+++ b/crates/ra_hir/src/code_model_impl/krate.rs
@@ -1,31 +1,28 @@
1use ra_db::CrateId;
2
3use crate::{ 1use crate::{
4 Crate, CrateDependency, AsName, Module, 2 Crate, CrateDependency, AsName, Module,
5 db::HirDatabase, 3 db::HirDatabase,
6}; 4};
7 5
8impl Crate { 6impl Crate {
9 pub(crate) fn new(crate_id: CrateId) -> Crate {
10 Crate { crate_id }
11 }
12 pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> { 7 pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> {
13 let crate_graph = db.crate_graph(); 8 let crate_graph = db.crate_graph();
14 crate_graph 9 crate_graph
15 .dependencies(self.crate_id) 10 .dependencies(self.crate_id)
16 .map(|dep| { 11 .map(|dep| {
17 let krate = Crate::new(dep.crate_id()); 12 let krate = Crate {
13 crate_id: dep.crate_id(),
14 };
18 let name = dep.as_name(); 15 let name = dep.as_name();
19 CrateDependency { krate, name } 16 CrateDependency { krate, name }
20 }) 17 })
21 .collect() 18 .collect()
22 } 19 }
23 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> { 20 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> {
24 let module_tree = db.module_tree(self.crate_id); 21 let module_tree = db.module_tree(*self);
25 let module_id = module_tree.modules().next()?; 22 let module_id = module_tree.modules().next()?;
26 23
27 let module = Module { 24 let module = Module {
28 krate: self.crate_id, 25 krate: *self,
29 module_id, 26 module_id,
30 }; 27 };
31 Some(module) 28 Some(module)
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 418d59c91..4a3901b8b 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -3,8 +3,9 @@ use ra_syntax::{ast, SyntaxNode, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Problem, 5 Module, ModuleSource, Problem,
6 Crate, Name, 6 Name,
7 module_tree::ModuleId, 7 module_tree::ModuleId,
8 impl_block::ImplId,
8 nameres::{lower::ImportId}, 9 nameres::{lower::ImportId},
9 db::HirDatabase, 10 db::HirDatabase,
10}; 11};
@@ -51,13 +52,19 @@ impl Module {
51 db: &impl HirDatabase, 52 db: &impl HirDatabase,
52 import: ImportId, 53 import: ImportId,
53 ) -> TreeArc<ast::PathSegment> { 54 ) -> TreeArc<ast::PathSegment> {
54 let source_map = db.lower_module_source_map(self.clone()); 55 let source_map = db.lower_module_source_map(*self);
55 let (_, source) = self.definition_source(db); 56 let (_, source) = self.definition_source(db);
56 source_map.get(&source, import) 57 source_map.get(&source, import)
57 } 58 }
58 59
59 pub(crate) fn krate_impl(&self, _db: &impl HirDatabase) -> Option<Crate> { 60 pub(crate) fn impl_source_impl(
60 Some(Crate::new(self.krate)) 61 &self,
62 db: &impl HirDatabase,
63 impl_id: ImplId,
64 ) -> TreeArc<ast::ImplBlock> {
65 let source_map = db.impls_in_module_source_map(*self);
66 let (_, source) = self.definition_source(db);
67 source_map.get(&source, impl_id)
61 } 68 }
62 69
63 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { 70 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 3f76b769d..189649841 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,20 +1,20 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceDatabase, CrateId, salsa}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
7 MacroCallId, HirFileId, 7 MacroCallId, HirFileId,
8 SourceFileItems, SourceItemId, Crate, Module, HirInterner, 8 SourceFileItems, SourceItemId, Crate, Module, HirInterner,
9 query_definitions, 9 query_definitions,
10 Function, FnSignature, FnScopes, 10 Function, FnSignature, ExprScopes,
11 Struct, Enum, StructField, 11 Struct, Enum, StructField,
12 macros::MacroExpansion, 12 macros::MacroExpansion,
13 module_tree::ModuleTree, 13 module_tree::ModuleTree,
14 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, 14 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
15 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, 15 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef},
16 adt::{StructData, EnumData}, 16 adt::{StructData, EnumData},
17 impl_block::ModuleImplBlocks, 17 impl_block::{ModuleImplBlocks, ImplSourceMap},
18 generics::{GenericParams, GenericDef}, 18 generics::{GenericParams, GenericDef},
19 ids::SourceFileItemId, 19 ids::SourceFileItemId,
20}; 20};
@@ -27,8 +27,8 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> {
27 #[salsa::invoke(crate::macros::expand_macro_invocation)] 27 #[salsa::invoke(crate::macros::expand_macro_invocation)]
28 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; 28 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
29 29
30 #[salsa::invoke(query_definitions::fn_scopes)] 30 #[salsa::invoke(ExprScopes::expr_scopes_query)]
31 fn fn_scopes(&self, func: Function) -> Arc<FnScopes>; 31 fn expr_scopes(&self, func: Function) -> Arc<ExprScopes>;
32 32
33 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 33 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
34 fn struct_data(&self, s: Struct) -> Arc<StructData>; 34 fn struct_data(&self, s: Struct) -> Arc<StructData>;
@@ -67,15 +67,24 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> {
67 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] 67 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)]
68 fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>; 68 fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>;
69 69
70 #[salsa::invoke(query_definitions::item_map)] 70 #[salsa::invoke(crate::nameres::ItemMap::item_map_query)]
71 fn item_map(&self, crate_id: CrateId) -> Arc<ItemMap>; 71 fn item_map(&self, krate: Crate) -> Arc<ItemMap>;
72 72
73 #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] 73 #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)]
74 fn module_tree(&self, crate_id: CrateId) -> Arc<ModuleTree>; 74 fn module_tree(&self, krate: Crate) -> Arc<ModuleTree>;
75
76 #[salsa::invoke(crate::impl_block::impls_in_module_with_source_map_query)]
77 fn impls_in_module_with_source_map(
78 &self,
79 module: Module,
80 ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>);
75 81
76 #[salsa::invoke(crate::impl_block::impls_in_module)] 82 #[salsa::invoke(crate::impl_block::impls_in_module)]
77 fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; 83 fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>;
78 84
85 #[salsa::invoke(crate::impl_block::impls_in_module_source_map_query)]
86 fn impls_in_module_source_map(&self, module: Module) -> Arc<ImplSourceMap>;
87
79 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 88 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
80 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 89 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
81 90
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 60d997bbe..37aa24677 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -16,6 +16,10 @@ use crate::{
16}; 16};
17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; 17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
20
21mod scope;
22
19#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct ExprId(RawId); 24pub struct ExprId(RawId);
21impl_arena_id!(ExprId); 25impl_arena_id!(ExprId);
@@ -215,7 +219,7 @@ pub use ra_syntax::ast::BinOp as BinaryOp;
215#[derive(Debug, Clone, Eq, PartialEq)] 219#[derive(Debug, Clone, Eq, PartialEq)]
216pub struct MatchArm { 220pub struct MatchArm {
217 pub pats: Vec<PatId>, 221 pub pats: Vec<PatId>,
218 // guard: Option<ExprId>, // TODO 222 pub guard: Option<ExprId>,
219 pub expr: ExprId, 223 pub expr: ExprId,
220} 224}
221 225
@@ -511,10 +515,12 @@ impl ExprCollector {
511 MatchArm { 515 MatchArm {
512 pats: vec![pat], 516 pats: vec![pat],
513 expr: then_branch, 517 expr: then_branch,
518 guard: None,
514 }, 519 },
515 MatchArm { 520 MatchArm {
516 pats: vec![placeholder_pat], 521 pats: vec![placeholder_pat],
517 expr: else_branch, 522 expr: else_branch,
523 guard: None,
518 }, 524 },
519 ]; 525 ];
520 self.alloc_expr( 526 self.alloc_expr(
@@ -613,6 +619,10 @@ impl ExprCollector {
613 .map(|arm| MatchArm { 619 .map(|arm| MatchArm {
614 pats: arm.pats().map(|p| self.collect_pat(p)).collect(), 620 pats: arm.pats().map(|p| self.collect_pat(p)).collect(),
615 expr: self.collect_expr_opt(arm.expr()), 621 expr: self.collect_expr_opt(arm.expr()),
622 guard: arm
623 .guard()
624 .and_then(|guard| guard.expr())
625 .map(|e| self.collect_expr(e)),
616 }) 626 })
617 .collect() 627 .collect()
618 } else { 628 } else {
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/expr/scope.rs
index c5d1de5eb..f8b5ba581 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -9,14 +9,18 @@ use ra_syntax::{
9}; 9};
10use ra_arena::{Arena, RawId, impl_arena_id}; 10use ra_arena::{Arena, RawId, impl_arena_id};
11 11
12use crate::{Name, AsName, expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}}; 12use crate::{
13 Name, AsName, Function,
14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping},
15 db::HirDatabase,
16};
13 17
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct ScopeId(RawId); 19pub struct ScopeId(RawId);
16impl_arena_id!(ScopeId); 20impl_arena_id!(ScopeId);
17 21
18#[derive(Debug, PartialEq, Eq)] 22#[derive(Debug, PartialEq, Eq)]
19pub struct FnScopes { 23pub struct ExprScopes {
20 body: Arc<Body>, 24 body: Arc<Body>,
21 scopes: Arena<ScopeId, ScopeData>, 25 scopes: Arena<ScopeId, ScopeData>,
22 scope_for: FxHashMap<ExprId, ScopeId>, 26 scope_for: FxHashMap<ExprId, ScopeId>,
@@ -34,9 +38,16 @@ pub struct ScopeData {
34 entries: Vec<ScopeEntry>, 38 entries: Vec<ScopeEntry>,
35} 39}
36 40
37impl FnScopes { 41impl ExprScopes {
38 pub(crate) fn new(body: Arc<Body>) -> FnScopes { 42 // TODO: This should take something more general than Function
39 let mut scopes = FnScopes { 43 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, function: Function) -> Arc<ExprScopes> {
44 let body = db.body_hir(function);
45 let res = ExprScopes::new(body);
46 Arc::new(res)
47 }
48
49 fn new(body: Arc<Body>) -> ExprScopes {
50 let mut scopes = ExprScopes {
40 body: body.clone(), 51 body: body.clone(),
41 scopes: Arena::default(), 52 scopes: Arena::default(),
42 scope_for: FxHashMap::default(), 53 scope_for: FxHashMap::default(),
@@ -119,7 +130,7 @@ impl FnScopes {
119#[derive(Debug, Clone, PartialEq, Eq)] 130#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct ScopesWithSyntaxMapping { 131pub struct ScopesWithSyntaxMapping {
121 pub syntax_mapping: Arc<BodySyntaxMapping>, 132 pub syntax_mapping: Arc<BodySyntaxMapping>,
122 pub scopes: Arc<FnScopes>, 133 pub scopes: Arc<ExprScopes>,
123} 134}
124 135
125#[derive(Debug, Clone, PartialEq, Eq)] 136#[derive(Debug, Clone, PartialEq, Eq)]
@@ -249,7 +260,7 @@ fn compute_block_scopes(
249 statements: &[Statement], 260 statements: &[Statement],
250 tail: Option<ExprId>, 261 tail: Option<ExprId>,
251 body: &Body, 262 body: &Body,
252 scopes: &mut FnScopes, 263 scopes: &mut ExprScopes,
253 mut scope: ScopeId, 264 mut scope: ScopeId,
254) { 265) {
255 for stmt in statements { 266 for stmt in statements {
@@ -275,7 +286,7 @@ fn compute_block_scopes(
275 } 286 }
276} 287}
277 288
278fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut FnScopes, scope: ScopeId) { 289fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
279 scopes.set_scope(expr, scope); 290 scopes.set_scope(expr, scope);
280 match &body[expr] { 291 match &body[expr] {
281 Expr::Block { statements, tail } => { 292 Expr::Block { statements, tail } => {
@@ -344,7 +355,7 @@ mod tests {
344 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 355 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
345 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 356 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
346 let body_hir = expr::collect_fn_body_syntax(fn_def); 357 let body_hir = expr::collect_fn_body_syntax(fn_def);
347 let scopes = FnScopes::new(Arc::clone(body_hir.body())); 358 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
348 let scopes = ScopesWithSyntaxMapping { 359 let scopes = ScopesWithSyntaxMapping {
349 scopes: Arc::new(scopes), 360 scopes: Arc::new(scopes),
350 syntax_mapping: Arc::new(body_hir), 361 syntax_mapping: Arc::new(body_hir),
@@ -444,7 +455,7 @@ mod tests {
444 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 455 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
445 456
446 let body_hir = expr::collect_fn_body_syntax(fn_def); 457 let body_hir = expr::collect_fn_body_syntax(fn_def);
447 let scopes = FnScopes::new(Arc::clone(body_hir.body())); 458 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
448 let scopes = ScopesWithSyntaxMapping { 459 let scopes = ScopesWithSyntaxMapping {
449 scopes: Arc::new(scopes), 460 scopes: Arc::new(scopes),
450 syntax_mapping: Arc::new(body_hir), 461 syntax_mapping: Arc::new(body_hir),
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 222e47349..5fc26324a 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -1,8 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
3 3
4use ra_arena::{Arena, RawId, impl_arena_id}; 4use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::{
6 AstPtr, SourceFile, TreeArc,
7ast::{self, AstNode}};
6 8
7use crate::{ 9use crate::{
8 Const, Type, 10 Const, Type,
@@ -14,6 +16,26 @@ use crate::{
14 16
15use crate::code_model_api::{Module, ModuleSource}; 17use crate::code_model_api::{Module, ModuleSource};
16 18
19#[derive(Debug, Default, PartialEq, Eq)]
20pub struct ImplSourceMap {
21 map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
22}
23
24impl ImplSourceMap {
25 fn insert(&mut self, impl_id: ImplId, impl_block: &ast::ImplBlock) {
26 self.map.insert(impl_id, AstPtr::new(impl_block))
27 }
28
29 pub fn get(&self, source: &ModuleSource, impl_id: ImplId) -> TreeArc<ast::ImplBlock> {
30 let file = match source {
31 ModuleSource::SourceFile(file) => &*file,
32 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
33 };
34
35 self.map[impl_id].to_node(file).to_owned()
36 }
37}
38
17#[derive(Debug, Clone, PartialEq, Eq)] 39#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct ImplBlock { 40pub struct ImplBlock {
19 module_impl_blocks: Arc<ModuleImplBlocks>, 41 module_impl_blocks: Arc<ModuleImplBlocks>,
@@ -39,6 +61,10 @@ impl ImplBlock {
39 } 61 }
40 } 62 }
41 63
64 pub fn id(&self) -> ImplId {
65 self.impl_id
66 }
67
42 fn impl_data(&self) -> &ImplData { 68 fn impl_data(&self) -> &ImplData {
43 &self.module_impl_blocks.impls[self.impl_id] 69 &self.module_impl_blocks.impls[self.impl_id]
44 } 70 }
@@ -148,7 +174,7 @@ impl ModuleImplBlocks {
148 } 174 }
149 } 175 }
150 176
151 fn collect(&mut self, db: &impl HirDatabase, module: Module) { 177 fn collect(&mut self, db: &impl HirDatabase, module: Module, source_map: &mut ImplSourceMap) {
152 let (file_id, module_source) = module.definition_source(db); 178 let (file_id, module_source) = module.definition_source(db);
153 let file_id: HirFileId = file_id.into(); 179 let file_id: HirFileId = file_id.into();
154 let node = match &module_source { 180 let node = match &module_source {
@@ -165,12 +191,31 @@ impl ModuleImplBlocks {
165 for &impl_item in &self.impls[id].items { 191 for &impl_item in &self.impls[id].items {
166 self.impls_by_def.insert(impl_item, id); 192 self.impls_by_def.insert(impl_item, id);
167 } 193 }
194
195 source_map.insert(id, impl_block_ast);
168 } 196 }
169 } 197 }
170} 198}
171 199
172pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> { 200pub(crate) fn impls_in_module_with_source_map_query(
201 db: &impl HirDatabase,
202 module: Module,
203) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
204 let mut source_map = ImplSourceMap::default();
205
173 let mut result = ModuleImplBlocks::new(); 206 let mut result = ModuleImplBlocks::new();
174 result.collect(db, module); 207 result.collect(db, module, &mut source_map);
175 Arc::new(result) 208
209 (Arc::new(result), Arc::new(source_map))
210}
211
212pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> {
213 db.impls_in_module_with_source_map(module).0
214}
215
216pub(crate) fn impls_in_module_source_map_query(
217 db: &impl HirDatabase,
218 module: Module,
219) -> Arc<ImplSourceMap> {
220 db.impls_in_module_with_source_map(module).1
176} 221}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index eaf8565ee..0b9ee63bf 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -57,9 +57,9 @@ pub use self::{
57 nameres::{ItemMap, PerNs, Namespace, Resolution}, 57 nameres::{ItemMap, PerNs, Namespace, Resolution},
58 ty::Ty, 58 ty::Ty,
59 impl_block::{ImplBlock, ImplItem}, 59 impl_block::{ImplBlock, ImplItem},
60 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
61 docs::{Docs, Documentation}, 60 docs::{Docs, Documentation},
62 adt::AdtDef, 61 adt::AdtDef,
62 expr::{ExprScopes, ScopesWithSyntaxMapping},
63}; 63};
64 64
65pub use self::code_model_api::{ 65pub use self::code_model_api::{
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index d1dc3fa4b..1f327eeb2 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
2 2
3use arrayvec::ArrayVec; 3use arrayvec::ArrayVec;
4use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
5use ra_db::{FileId, SourceRoot, CrateId}; 5use ra_db::{FileId, SourceRoot};
6use ra_syntax::{ 6use ra_syntax::{
7 SyntaxNode, TreeArc, 7 SyntaxNode, TreeArc,
8 algo::generate, 8 algo::generate,
@@ -13,6 +13,7 @@ use test_utils::tested_by;
13 13
14use crate::{ 14use crate::{
15 Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, 15 Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource,
16 Crate,
16 ids::SourceFileItemId, 17 ids::SourceFileItemId,
17}; 18};
18 19
@@ -132,10 +133,10 @@ struct LinkData {
132} 133}
133 134
134impl ModuleTree { 135impl ModuleTree {
135 pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ModuleTree> { 136 pub(crate) fn module_tree_query(db: &impl HirDatabase, krate: Crate) -> Arc<ModuleTree> {
136 db.check_canceled(); 137 db.check_canceled();
137 let mut res = ModuleTree::default(); 138 let mut res = ModuleTree::default();
138 res.init_crate(db, crate_id); 139 res.init_crate(db, krate);
139 Arc::new(res) 140 Arc::new(res)
140 } 141 }
141 142
@@ -155,9 +156,9 @@ impl ModuleTree {
155 Some(res) 156 Some(res)
156 } 157 }
157 158
158 fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) { 159 fn init_crate(&mut self, db: &impl HirDatabase, krate: Crate) {
159 let crate_graph = db.crate_graph(); 160 let crate_graph = db.crate_graph();
160 let file_id = crate_graph.crate_root(crate_id); 161 let file_id = crate_graph.crate_root(krate.crate_id);
161 let source_root_id = db.file_source_root(file_id); 162 let source_root_id = db.file_source_root(file_id);
162 163
163 let source_root = db.source_root(source_root_id); 164 let source_root = db.source_root(source_root_id);
@@ -172,6 +173,7 @@ impl ModuleTree {
172 file_id: HirFileId, 173 file_id: HirFileId,
173 decl_id: Option<SourceFileItemId>, 174 decl_id: Option<SourceFileItemId>,
174 ) -> ModuleId { 175 ) -> ModuleId {
176 let is_root = parent.is_none();
175 let id = self.alloc_mod(ModuleData { 177 let id = self.alloc_mod(ModuleData {
176 file_id, 178 file_id,
177 decl_id, 179 decl_id,
@@ -191,7 +193,7 @@ impl ModuleTree {
191 }); 193 });
192 194
193 let (points_to, problem) = if sub.is_declaration { 195 let (points_to, problem) = if sub.is_declaration {
194 let (points_to, problem) = resolve_submodule(db, file_id, &sub.name); 196 let (points_to, problem) = resolve_submodule(db, file_id, &sub.name, is_root);
195 let points_to = points_to 197 let points_to = points_to
196 .into_iter() 198 .into_iter()
197 .map(|file_id| { 199 .map(|file_id| {
@@ -295,6 +297,7 @@ fn resolve_submodule(
295 db: &impl HirDatabase, 297 db: &impl HirDatabase,
296 file_id: HirFileId, 298 file_id: HirFileId,
297 name: &Name, 299 name: &Name,
300 is_root: bool,
298) -> (Vec<FileId>, Option<Problem>) { 301) -> (Vec<FileId>, Option<Problem>) {
299 // FIXME: handle submodules of inline modules properly 302 // FIXME: handle submodules of inline modules properly
300 let file_id = file_id.original_file(db); 303 let file_id = file_id.original_file(db);
@@ -303,7 +306,7 @@ fn resolve_submodule(
303 let root = RelativePathBuf::default(); 306 let root = RelativePathBuf::default();
304 let dir_path = path.parent().unwrap_or(&root); 307 let dir_path = path.parent().unwrap_or(&root);
305 let mod_name = path.file_stem().unwrap_or("unknown"); 308 let mod_name = path.file_stem().unwrap_or("unknown");
306 let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; 309 let is_dir_owner = is_root || mod_name == "mod";
307 310
308 let file_mod = dir_path.join(format!("{}.rs", name)); 311 let file_mod = dir_path.join(format!("{}.rs", name));
309 let dir_mod = dir_path.join(format!("{}/mod.rs", name)); 312 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 97ce6c946..4573a72ba 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -16,9 +16,8 @@
16//! structure itself is modified. 16//! structure itself is modified.
17pub(crate) mod lower; 17pub(crate) mod lower;
18 18
19use std::sync::Arc; 19use std::{time, sync::Arc};
20 20
21use ra_db::CrateId;
22use ra_arena::map::ArenaMap; 21use ra_arena::map::ArenaMap;
23use test_utils::tested_by; 22use test_utils::tested_by;
24use rustc_hash::{FxHashMap, FxHashSet}; 23use rustc_hash::{FxHashMap, FxHashSet};
@@ -156,10 +155,10 @@ impl<T> PerNs<T> {
156 } 155 }
157} 156}
158 157
159pub(crate) struct Resolver<'a, DB> { 158struct Resolver<'a, DB> {
160 db: &'a DB, 159 db: &'a DB,
161 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, 160 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
162 krate: CrateId, 161 krate: Crate,
163 module_tree: Arc<ModuleTree>, 162 module_tree: Arc<ModuleTree>,
164 processed_imports: FxHashSet<(ModuleId, ImportId)>, 163 processed_imports: FxHashSet<(ModuleId, ImportId)>,
165 result: ItemMap, 164 result: ItemMap,
@@ -169,10 +168,10 @@ impl<'a, DB> Resolver<'a, DB>
169where 168where
170 DB: HirDatabase, 169 DB: HirDatabase,
171{ 170{
172 pub(crate) fn new( 171 fn new(
173 db: &'a DB, 172 db: &'a DB,
174 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, 173 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
175 krate: CrateId, 174 krate: Crate,
176 ) -> Resolver<'a, DB> { 175 ) -> Resolver<'a, DB> {
177 let module_tree = db.module_tree(krate); 176 let module_tree = db.module_tree(krate);
178 Resolver { 177 Resolver {
@@ -219,7 +218,7 @@ where
219 let crate_graph = self.db.crate_graph(); 218 let crate_graph = self.db.crate_graph();
220 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) 219 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file())
221 { 220 {
222 let krate = Crate::new(crate_id); 221 let krate = Crate { crate_id };
223 for dep in krate.dependencies(self.db) { 222 for dep in krate.dependencies(self.db) {
224 if let Some(module) = dep.krate.root_module(self.db) { 223 if let Some(module) = dep.krate.root_module(self.db) {
225 let def = module.into(); 224 let def = module.into();
@@ -331,6 +330,26 @@ enum ReachedFixedPoint {
331} 330}
332 331
333impl ItemMap { 332impl ItemMap {
333 pub(crate) fn item_map_query(db: &impl HirDatabase, krate: Crate) -> Arc<ItemMap> {
334 let start = time::Instant::now();
335 let module_tree = db.module_tree(krate);
336 let input = module_tree
337 .modules()
338 .map(|module_id| {
339 (
340 module_id,
341 db.lower_module_module(Module { krate, module_id }),
342 )
343 })
344 .collect::<FxHashMap<_, _>>();
345
346 let resolver = Resolver::new(db, &input, krate);
347 let res = resolver.resolve();
348 let elapsed = start.elapsed();
349 log::info!("item_map: {:?}", elapsed);
350 Arc::new(res)
351 }
352
334 pub(crate) fn resolve_path( 353 pub(crate) fn resolve_path(
335 &self, 354 &self,
336 db: &impl HirDatabase, 355 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index e72781f51..9c5ca097e 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -16,7 +16,21 @@ fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
16 let module = crate::source_binder::module_from_position(&db, pos).unwrap(); 16 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
17 let krate = module.krate(&db).unwrap(); 17 let krate = module.krate(&db).unwrap();
18 let module_id = module.module_id; 18 let module_id = module.module_id;
19 (db.item_map(krate.crate_id), module_id) 19 (db.item_map(krate), module_id)
20}
21
22/// Sets the crate root to the file of the cursor marker
23fn item_map_custom_crate_root(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
24 let (mut db, pos) = MockDatabase::with_position(fixture);
25
26 let mut crate_graph = CrateGraph::default();
27 crate_graph.add_crate_root(pos.file_id);
28 db.set_crate_graph(Arc::new(crate_graph));
29
30 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
31 let krate = module.krate(&db).unwrap();
32 let module_id = module.module_id;
33 (db.item_map(krate), module_id)
20} 34}
21 35
22fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { 36fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
@@ -134,6 +148,28 @@ fn re_exports() {
134} 148}
135 149
136#[test] 150#[test]
151fn module_resolution_works_for_non_standard_filenames() {
152 let (item_map, module_id) = item_map_custom_crate_root(
153 "
154 //- /my_library.rs
155 mod foo;
156 use self::foo::Bar;
157 <|>
158 //- /foo/mod.rs
159 pub struct Bar;
160 ",
161 );
162 check_module_item_map(
163 &item_map,
164 module_id,
165 "
166 Bar: t v
167 foo: t
168 ",
169 );
170}
171
172#[test]
137fn name_res_works_for_broken_modules() { 173fn name_res_works_for_broken_modules() {
138 covers!(name_res_works_for_broken_modules); 174 covers!(name_res_works_for_broken_modules);
139 let (item_map, module_id) = item_map( 175 let (item_map, module_id) = item_map(
@@ -261,7 +297,7 @@ fn item_map_across_crates() {
261 297
262 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 298 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
263 let krate = module.krate(&db).unwrap(); 299 let krate = module.krate(&db).unwrap();
264 let item_map = db.item_map(krate.crate_id); 300 let item_map = db.item_map(krate);
265 301
266 check_module_item_map( 302 check_module_item_map(
267 &item_map, 303 &item_map,
@@ -313,7 +349,7 @@ fn import_across_source_roots() {
313 349
314 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 350 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
315 let krate = module.krate(&db).unwrap(); 351 let krate = module.krate(&db).unwrap();
316 let item_map = db.item_map(krate.crate_id); 352 let item_map = db.item_map(krate);
317 353
318 check_module_item_map( 354 check_module_item_map(
319 &item_map, 355 &item_map,
@@ -355,7 +391,7 @@ fn reexport_across_crates() {
355 391
356 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 392 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
357 let krate = module.krate(&db).unwrap(); 393 let krate = module.krate(&db).unwrap();
358 let item_map = db.item_map(krate.crate_id); 394 let item_map = db.item_map(krate);
359 395
360 check_module_item_map( 396 check_module_item_map(
361 &item_map, 397 &item_map,
@@ -373,7 +409,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
373 let krate = module.krate(&db).unwrap(); 409 let krate = module.krate(&db).unwrap();
374 { 410 {
375 let events = db.log_executed(|| { 411 let events = db.log_executed(|| {
376 db.item_map(krate.crate_id); 412 db.item_map(krate);
377 }); 413 });
378 assert!(format!("{:?}", events).contains("item_map")) 414 assert!(format!("{:?}", events).contains("item_map"))
379 } 415 }
@@ -381,7 +417,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
381 417
382 { 418 {
383 let events = db.log_executed(|| { 419 let events = db.log_executed(|| {
384 db.item_map(krate.crate_id); 420 db.item_map(krate);
385 }); 421 });
386 assert!( 422 assert!(
387 !format!("{:?}", events).contains("item_map"), 423 !format!("{:?}", events).contains("item_map"),
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index bf9ac0dfb..734a98282 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -1,25 +1,14 @@
1use std::{ 1use std::sync::Arc;
2 sync::Arc,
3 time::Instant,
4};
5 2
6use rustc_hash::FxHashMap; 3use ra_syntax::{
7use ra_syntax::{SyntaxNode, TreeArc}; 4 SyntaxNode, TreeArc,
8use ra_db::{CrateId}; 5};
9 6
10use crate::{ 7use crate::{
11 SourceFileItems, SourceItemId, HirFileId, 8 SourceFileItems, SourceItemId, HirFileId,
12 Function, FnScopes, Module,
13 db::HirDatabase, 9 db::HirDatabase,
14 nameres::{ItemMap, Resolver},
15}; 10};
16 11
17pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> {
18 let body = db.body_hir(func);
19 let res = FnScopes::new(body);
20 Arc::new(res)
21}
22
23pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { 12pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> {
24 let source_file = db.hir_parse(file_id); 13 let source_file = db.hir_parse(file_id);
25 let res = SourceFileItems::new(file_id, &source_file); 14 let res = SourceFileItems::new(file_id, &source_file);
@@ -35,26 +24,3 @@ pub(super) fn file_item(
35 .to_node(&source_file) 24 .to_node(&source_file)
36 .to_owned() 25 .to_owned()
37} 26}
38
39pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> {
40 let start = Instant::now();
41 let module_tree = db.module_tree(crate_id);
42 let input = module_tree
43 .modules()
44 .map(|module_id| {
45 (
46 module_id,
47 db.lower_module_module(Module {
48 krate: crate_id,
49 module_id,
50 }),
51 )
52 })
53 .collect::<FxHashMap<_, _>>();
54
55 let resolver = Resolver::new(db, &input, crate_id);
56 let res = resolver.resolve();
57 let elapsed = start.elapsed();
58 log::info!("item_map: {:?}", elapsed);
59 Arc::new(res)
60}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index f523f0647..d1eaccf23 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,8 +13,8 @@ use ra_syntax::{
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, ModuleDef, 16 HirDatabase, Function, ModuleDef, Struct, Enum,
17 AsName, Module, HirFileId, 17 AsName, Module, HirFileId, Crate,
18 ids::{LocationCtx, SourceFileItemId}, 18 ids::{LocationCtx, SourceFileItemId},
19}; 19};
20 20
@@ -83,7 +83,8 @@ fn module_from_source(
83 let source_root_id = db.file_source_root(file_id.as_original_file()); 83 let source_root_id = db.file_source_root(file_id.as_original_file());
84 db.source_root_crates(source_root_id) 84 db.source_root_crates(source_root_id)
85 .iter() 85 .iter()
86 .find_map(|&krate| { 86 .map(|&crate_id| Crate { crate_id })
87 .find_map(|krate| {
87 let module_tree = db.module_tree(krate); 88 let module_tree = db.module_tree(krate);
88 let module_id = module_tree.find_module_by_source(file_id, decl_id)?; 89 let module_id = module_tree.find_module_by_source(file_id, decl_id)?;
89 Some(Module { krate, module_id }) 90 Some(Module { krate, module_id })
@@ -128,6 +129,28 @@ pub fn function_from_child_node(
128 function_from_source(db, file_id, fn_def) 129 function_from_source(db, file_id, fn_def)
129} 130}
130 131
132pub fn struct_from_module(
133 db: &impl HirDatabase,
134 module: Module,
135 struct_def: &ast::StructDef,
136) -> Struct {
137 let (file_id, _) = module.definition_source(db);
138 let file_id = file_id.into();
139 let ctx = LocationCtx::new(db, module, file_id);
140 Struct {
141 id: ctx.to_def(struct_def),
142 }
143}
144
145pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
146 let (file_id, _) = module.definition_source(db);
147 let file_id = file_id.into();
148 let ctx = LocationCtx::new(db, module, file_id);
149 Enum {
150 id: ctx.to_def(enum_def),
151 }
152}
153
131pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { 154pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> {
132 let module = match module_from_file_id(db, file_id) { 155 let module = match module_from_file_id(db, file_id) {
133 Some(it) => it, 156 Some(it) => it,
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 31ea45706..60c231e82 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -20,6 +20,7 @@ mod tests;
20pub(crate) mod method_resolution; 20pub(crate) mod method_resolution;
21 21
22use std::borrow::Cow; 22use std::borrow::Cow;
23use std::iter::repeat;
23use std::ops::Index; 24use std::ops::Index;
24use std::sync::Arc; 25use std::sync::Arc;
25use std::{fmt, mem}; 26use std::{fmt, mem};
@@ -33,7 +34,7 @@ use test_utils::tested_by;
33 34
34use crate::{ 35use crate::{
35 Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, 36 Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock,
36 FnSignature, FnScopes, ModuleDef, AdtDef, 37 FnSignature, ExprScopes, ModuleDef, AdtDef,
37 db::HirDatabase, 38 db::HirDatabase,
38 type_ref::{TypeRef, Mutability}, 39 type_ref::{TypeRef, Mutability},
39 name::KnownName, 40 name::KnownName,
@@ -185,7 +186,7 @@ pub enum Ty {
185 186
186 /// Structures, enumerations and unions. 187 /// Structures, enumerations and unions.
187 Adt { 188 Adt {
188 /// The DefId of the struct/enum. 189 /// The definition of the struct/enum.
189 def_id: AdtDef, 190 def_id: AdtDef,
190 /// The name, for displaying. 191 /// The name, for displaying.
191 name: Name, 192 name: Name,
@@ -209,6 +210,27 @@ pub enum Ty {
209 /// `&'a mut T` or `&'a T`. 210 /// `&'a mut T` or `&'a T`.
210 Ref(Arc<Ty>, Mutability), 211 Ref(Arc<Ty>, Mutability),
211 212
213 /// The anonymous type of a function declaration/definition. Each
214 /// function has a unique type, which is output (for a function
215 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
216 ///
217 /// For example the type of `bar` here:
218 ///
219 /// ```rust
220 /// fn foo() -> i32 { 1 }
221 /// let bar = foo; // bar: fn() -> i32 {foo}
222 /// ```
223 FnDef {
224 // Function definition
225 def: Function,
226 /// For display
227 name: Name,
228 /// Parameters and return type
229 sig: Arc<FnSig>,
230 /// Substitutions for the generic parameters of the type
231 substs: Substs,
232 },
233
212 /// A pointer to a function. Written as `fn() -> i32`. 234 /// A pointer to a function. Written as `fn() -> i32`.
213 /// 235 ///
214 /// For example the type of `bar` here: 236 /// For example the type of `bar` here:
@@ -448,12 +470,12 @@ impl Ty {
448 } 470 }
449 // add placeholders for args that were not provided 471 // add placeholders for args that were not provided
450 // TODO: handle defaults 472 // TODO: handle defaults
451 for _ in segment 473 let supplied_params = segment
452 .args_and_bindings 474 .args_and_bindings
453 .as_ref() 475 .as_ref()
454 .map(|ga| ga.args.len()) 476 .map(|ga| ga.args.len())
455 .unwrap_or(0)..def_generics.params.len() 477 .unwrap_or(0);
456 { 478 for _ in supplied_params..def_generics.params.len() {
457 substs.push(Ty::Unknown); 479 substs.push(Ty::Unknown);
458 } 480 }
459 assert_eq!(substs.len(), def_generics.params.len()); 481 assert_eq!(substs.len(), def_generics.params.len());
@@ -485,6 +507,19 @@ impl Ty {
485 } 507 }
486 sig_mut.output.walk_mut(f); 508 sig_mut.output.walk_mut(f);
487 } 509 }
510 Ty::FnDef { substs, sig, .. } => {
511 let sig_mut = Arc::make_mut(sig);
512 for input in &mut sig_mut.input {
513 input.walk_mut(f);
514 }
515 sig_mut.output.walk_mut(f);
516 // Without an Arc::make_mut_slice, we can't avoid the clone here:
517 let mut v: Vec<_> = substs.0.iter().cloned().collect();
518 for t in &mut v {
519 t.walk_mut(f);
520 }
521 substs.0 = v.into();
522 }
488 Ty::Adt { substs, .. } => { 523 Ty::Adt { substs, .. } => {
489 // Without an Arc::make_mut_slice, we can't avoid the clone here: 524 // Without an Arc::make_mut_slice, we can't avoid the clone here:
490 let mut v: Vec<_> = substs.0.iter().cloned().collect(); 525 let mut v: Vec<_> = substs.0.iter().cloned().collect();
@@ -524,6 +559,12 @@ impl Ty {
524 name, 559 name,
525 substs, 560 substs,
526 }, 561 },
562 Ty::FnDef { def, name, sig, .. } => Ty::FnDef {
563 def,
564 name,
565 sig,
566 substs,
567 },
527 _ => self, 568 _ => self,
528 } 569 }
529 } 570 }
@@ -551,7 +592,7 @@ impl Ty {
551 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 592 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
552 fn substs(&self) -> Option<Substs> { 593 fn substs(&self) -> Option<Substs> {
553 match self { 594 match self {
554 Ty::Adt { substs, .. } => Some(substs.clone()), 595 Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()),
555 _ => None, 596 _ => None,
556 } 597 }
557 } 598 }
@@ -586,6 +627,22 @@ impl fmt::Display for Ty {
586 .to_fmt(f)?; 627 .to_fmt(f)?;
587 write!(f, " -> {}", sig.output) 628 write!(f, " -> {}", sig.output)
588 } 629 }
630 Ty::FnDef {
631 name, substs, sig, ..
632 } => {
633 write!(f, "fn {}", name)?;
634 if substs.0.len() > 0 {
635 join(substs.0.iter())
636 .surround_with("<", ">")
637 .separator(", ")
638 .to_fmt(f)?;
639 }
640 join(sig.input.iter())
641 .surround_with("(", ")")
642 .separator(", ")
643 .to_fmt(f)?;
644 write!(f, " -> {}", sig.output)
645 }
589 Ty::Adt { name, substs, .. } => { 646 Ty::Adt { name, substs, .. } => {
590 write!(f, "{}", name)?; 647 write!(f, "{}", name)?;
591 if substs.0.len() > 0 { 648 if substs.0.len() > 0 {
@@ -607,11 +664,11 @@ impl fmt::Display for Ty {
607 664
608/// Compute the declared type of a function. This should not need to look at the 665/// Compute the declared type of a function. This should not need to look at the
609/// function body. 666/// function body.
610fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { 667fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
611 let signature = f.signature(db); 668 let signature = def.signature(db);
612 let module = f.module(db); 669 let module = def.module(db);
613 let impl_block = f.impl_block(db); 670 let impl_block = def.impl_block(db);
614 let generics = f.generic_params(db); 671 let generics = def.generic_params(db);
615 let input = signature 672 let input = signature
616 .params() 673 .params()
617 .iter() 674 .iter()
@@ -624,8 +681,15 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
624 &generics, 681 &generics,
625 signature.ret_type(), 682 signature.ret_type(),
626 ); 683 );
627 let sig = FnSig { input, output }; 684 let sig = Arc::new(FnSig { input, output });
628 Ty::FnPtr(Arc::new(sig)) 685 let substs = make_substs(&generics);
686 let name = def.name(db);
687 Ty::FnDef {
688 def,
689 sig,
690 name,
691 substs,
692 }
629} 693}
630 694
631fn make_substs(generics: &GenericParams) -> Substs { 695fn make_substs(generics: &GenericParams) -> Substs {
@@ -750,7 +814,7 @@ impl Index<PatId> for InferenceResult {
750struct InferenceContext<'a, D: HirDatabase> { 814struct InferenceContext<'a, D: HirDatabase> {
751 db: &'a D, 815 db: &'a D,
752 body: Arc<Body>, 816 body: Arc<Body>,
753 scopes: Arc<FnScopes>, 817 scopes: Arc<ExprScopes>,
754 module: Module, 818 module: Module,
755 impl_block: Option<ImplBlock>, 819 impl_block: Option<ImplBlock>,
756 var_unification_table: InPlaceUnificationTable<TypeVarId>, 820 var_unification_table: InPlaceUnificationTable<TypeVarId>,
@@ -844,7 +908,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
844 fn new( 908 fn new(
845 db: &'a D, 909 db: &'a D,
846 body: Arc<Body>, 910 body: Arc<Body>,
847 scopes: Arc<FnScopes>, 911 scopes: Arc<ExprScopes>,
848 module: Module, 912 module: Module,
849 impl_block: Option<ImplBlock>, 913 impl_block: Option<ImplBlock>,
850 ) -> Self { 914 ) -> Self {
@@ -1102,7 +1166,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1102 .into(); 1166 .into();
1103 let typable = typable?; 1167 let typable = typable?;
1104 let ty = self.db.type_for_def(typable); 1168 let ty = self.db.type_for_def(typable);
1169 let generics = GenericParams::default();
1170 let substs = Ty::substs_from_path(
1171 self.db,
1172 &self.module,
1173 self.impl_block.as_ref(),
1174 &generics,
1175 path,
1176 typable,
1177 );
1178 let ty = ty.apply_substs(substs);
1105 let ty = self.insert_type_vars(ty); 1179 let ty = self.insert_type_vars(ty);
1180
1106 Some(ty) 1181 Some(ty)
1107 } 1182 }
1108 1183
@@ -1142,7 +1217,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1142 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1217 let ty = self.insert_type_vars(ty.apply_substs(substs));
1143 (ty, Some(var.into())) 1218 (ty, Some(var.into()))
1144 } 1219 }
1145 TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), 1220 TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None),
1146 } 1221 }
1147 } 1222 }
1148 1223
@@ -1196,9 +1271,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1196 Ty::Tuple(ref tuple_args) => &**tuple_args, 1271 Ty::Tuple(ref tuple_args) => &**tuple_args,
1197 _ => &[], 1272 _ => &[],
1198 }; 1273 };
1199 let expectations_iter = expectations 1274 let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown));
1200 .into_iter()
1201 .chain(std::iter::repeat(&Ty::Unknown));
1202 1275
1203 let inner_tys = args 1276 let inner_tys = args
1204 .iter() 1277 .iter()
@@ -1332,18 +1405,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1332 Expr::Call { callee, args } => { 1405 Expr::Call { callee, args } => {
1333 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 1406 let callee_ty = self.infer_expr(*callee, &Expectation::none());
1334 let (param_tys, ret_ty) = match &callee_ty { 1407 let (param_tys, ret_ty) = match &callee_ty {
1335 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), 1408 Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
1409 Ty::FnDef { substs, sig, .. } => {
1410 let ret_ty = sig.output.clone().subst(&substs);
1411 let param_tys = sig
1412 .input
1413 .iter()
1414 .map(|ty| ty.clone().subst(&substs))
1415 .collect();
1416 (param_tys, ret_ty)
1417 }
1336 _ => { 1418 _ => {
1337 // not callable 1419 // not callable
1338 // TODO report an error? 1420 // TODO report an error?
1339 (&[][..], Ty::Unknown) 1421 (Vec::new(), Ty::Unknown)
1340 } 1422 }
1341 }; 1423 };
1342 for (i, arg) in args.iter().enumerate() { 1424 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1343 self.infer_expr( 1425 for (arg, param) in args.iter().zip(param_iter) {
1344 *arg, 1426 self.infer_expr(*arg, &Expectation::has_type(param));
1345 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
1346 );
1347 } 1427 }
1348 ret_ty 1428 ret_ty
1349 } 1429 }
@@ -1365,21 +1445,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1365 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1445 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
1366 Ty::FnPtr(sig) => { 1446 Ty::FnPtr(sig) => {
1367 if sig.input.len() > 0 { 1447 if sig.input.len() > 0 {
1368 (&sig.input[0], &sig.input[1..], sig.output.clone()) 1448 (
1449 sig.input[0].clone(),
1450 sig.input[1..].iter().cloned().collect(),
1451 sig.output.clone(),
1452 )
1453 } else {
1454 (Ty::Unknown, Vec::new(), sig.output.clone())
1455 }
1456 }
1457 Ty::FnDef { substs, sig, .. } => {
1458 let ret_ty = sig.output.clone().subst(&substs);
1459
1460 if sig.input.len() > 0 {
1461 let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs));
1462 let receiver_ty = arg_iter.next().unwrap();
1463 (receiver_ty, arg_iter.collect(), ret_ty)
1369 } else { 1464 } else {
1370 (&Ty::Unknown, &[][..], sig.output.clone()) 1465 (Ty::Unknown, Vec::new(), ret_ty)
1371 } 1466 }
1372 } 1467 }
1373 _ => (&Ty::Unknown, &[][..], Ty::Unknown), 1468 _ => (Ty::Unknown, Vec::new(), Ty::Unknown),
1374 }; 1469 };
1375 // TODO we would have to apply the autoderef/autoref steps here 1470 // TODO we would have to apply the autoderef/autoref steps here
1376 // to get the correct receiver type to unify... 1471 // to get the correct receiver type to unify...
1377 self.unify(expected_receiver_ty, &receiver_ty); 1472 self.unify(&expected_receiver_ty, &receiver_ty);
1378 for (i, arg) in args.iter().enumerate() { 1473 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1379 self.infer_expr( 1474 for (arg, param) in args.iter().zip(param_iter) {
1380 *arg, 1475 self.infer_expr(*arg, &Expectation::has_type(param));
1381 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
1382 );
1383 } 1476 }
1384 ret_ty 1477 ret_ty
1385 } 1478 }
@@ -1395,7 +1488,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1395 for &pat in &arm.pats { 1488 for &pat in &arm.pats {
1396 let _pat_ty = self.infer_pat(pat, &input_ty); 1489 let _pat_ty = self.infer_pat(pat, &input_ty);
1397 } 1490 }
1398 // TODO type the guard 1491 if let Some(guard_expr) = arm.guard {
1492 self.infer_expr(guard_expr, &Expectation::has_type(Ty::Bool));
1493 }
1399 self.infer_expr(arm.expr, &expected); 1494 self.infer_expr(arm.expr, &expected);
1400 } 1495 }
1401 1496
@@ -1468,9 +1563,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1468 cast_ty 1563 cast_ty
1469 } 1564 }
1470 Expr::Ref { expr, mutability } => { 1565 Expr::Ref { expr, mutability } => {
1471 // TODO pass the expectation down 1566 let expectation = if let Ty::Ref(ref subty, expected_mutability) = expected.ty {
1472 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 1567 if expected_mutability == Mutability::Mut && *mutability == Mutability::Shared {
1568 // TODO: throw type error - expected mut reference but found shared ref,
1569 // which cannot be coerced
1570 }
1571 Expectation::has_type((**subty).clone())
1572 } else {
1573 Expectation::none()
1574 };
1473 // TODO reference coercions etc. 1575 // TODO reference coercions etc.
1576 let inner_ty = self.infer_expr(*expr, &expectation);
1474 Ty::Ref(Arc::new(inner_ty), *mutability) 1577 Ty::Ref(Arc::new(inner_ty), *mutability)
1475 } 1578 }
1476 Expr::UnaryOp { expr, op } => { 1579 Expr::UnaryOp { expr, op } => {
@@ -1495,9 +1598,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1495 _ => Ty::Unknown, 1598 _ => Ty::Unknown,
1496 } 1599 }
1497 } 1600 }
1498 UnaryOp::Not if inner_ty == Ty::Bool => Ty::Bool, 1601 UnaryOp::Not => {
1499 // TODO: resolve ops::Not trait for inner_ty 1602 match inner_ty {
1500 UnaryOp::Not => Ty::Unknown, 1603 Ty::Bool | Ty::Int(_) | Ty::Infer(InferTy::IntVar(..)) => inner_ty,
1604 // TODO: resolve ops::Not trait for inner_ty
1605 _ => Ty::Unknown,
1606 }
1607 }
1501 } 1608 }
1502 } 1609 }
1503 Expr::BinaryOp { lhs, rhs, op } => match op { 1610 Expr::BinaryOp { lhs, rhs, op } => match op {
@@ -1609,10 +1716,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1609 1716
1610 self.infer_pat(*pat, &ty); 1717 self.infer_pat(*pat, &ty);
1611 } 1718 }
1612 self.return_ty = { 1719 self.return_ty = self.make_ty(signature.ret_type());
1613 let ty = self.make_ty(signature.ret_type());
1614 ty
1615 };
1616 } 1720 }
1617 1721
1618 fn infer_body(&mut self) { 1722 fn infer_body(&mut self) {
@@ -1626,7 +1730,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1626pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 1730pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
1627 db.check_canceled(); 1731 db.check_canceled();
1628 let body = func.body(db); 1732 let body = func.body(db);
1629 let scopes = db.fn_scopes(func); 1733 let scopes = db.expr_scopes(func);
1630 let module = func.module(db); 1734 let module = func.module(db);
1631 let impl_block = func.impl_block(db); 1735 let impl_block = func.impl_block(db);
1632 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1736 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 9a571c2aa..37bc3f38c 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -44,7 +44,7 @@ impl CrateImplBlocks {
44 &'a self, 44 &'a self,
45 db: &'a impl HirDatabase, 45 db: &'a impl HirDatabase,
46 ty: &Ty, 46 ty: &Ty,
47 ) -> impl Iterator<Item = ImplBlock> + 'a { 47 ) -> impl Iterator<Item = (Module, ImplBlock)> + 'a {
48 let fingerprint = TyFingerprint::for_impl(ty); 48 let fingerprint = TyFingerprint::for_impl(ty);
49 fingerprint 49 fingerprint
50 .and_then(|f| self.impls.get(&f)) 50 .and_then(|f| self.impls.get(&f))
@@ -52,11 +52,11 @@ impl CrateImplBlocks {
52 .flat_map(|i| i.iter()) 52 .flat_map(|i| i.iter())
53 .map(move |(module_id, impl_id)| { 53 .map(move |(module_id, impl_id)| {
54 let module = Module { 54 let module = Module {
55 krate: self.krate.crate_id, 55 krate: self.krate,
56 module_id: *module_id, 56 module_id: *module_id,
57 }; 57 };
58 let module_impl_blocks = db.impls_in_module(module); 58 let module_impl_blocks = db.impls_in_module(module);
59 ImplBlock::from_id(module_impl_blocks, *impl_id) 59 (module, ImplBlock::from_id(module_impl_blocks, *impl_id))
60 }) 60 })
61 } 61 }
62 62
@@ -152,7 +152,7 @@ impl Ty {
152 }; 152 };
153 let impls = db.impls_in_crate(krate); 153 let impls = db.impls_in_crate(krate);
154 154
155 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) { 155 for (_, impl_block) in impls.lookup_impl_blocks(db, &derefed_ty) {
156 for item in impl_block.items() { 156 for item in impl_block.items() {
157 match item { 157 match item {
158 ImplItem::Method(f) => { 158 ImplItem::Method(f) => {
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap
index 2719f592e..48c83cbb2 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap
@@ -1,10 +1,10 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-28T21:58:55.559331849+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[68; 262) '{ ... d; }': () 7[68; 289) '{ ... d; }': ()
8[78; 79) 'e': E 8[78; 79) 'e': E
9[82; 95) 'E::A { x: 3 }': E 9[82; 95) 'E::A { x: 3 }': E
10[92; 93) '3': usize 10[92; 93) '3': usize
@@ -15,15 +15,18 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
15[129; 148) 'E::A {..._var }': E 15[129; 148) 'E::A {..._var }': E
16[139; 146) 'new_var': usize 16[139; 146) 'new_var': usize
17[151; 152) 'e': E 17[151; 152) 'e': E
18[159; 218) 'match ... }': usize 18[159; 245) 'match ... }': usize
19[165; 166) 'e': E 19[165; 166) 'e': E
20[177; 187) 'E::A { x }': E 20[177; 187) 'E::A { x }': E
21[184; 185) 'x': usize 21[184; 185) 'x': usize
22[191; 192) 'x': usize 22[191; 192) 'x': usize
23[202; 206) 'E::B': E 23[202; 206) 'E::B': E
24[210; 211) '1': usize 24[210; 213) 'foo': bool
25[229; 248) 'ref d ...{ .. }': &E 25[217; 218) '1': usize
26[237; 248) 'E::A { .. }': E 26[228; 232) 'E::B': E
27[251; 252) 'e': E 27[236; 238) '10': usize
28[258; 259) 'd': &E 28[256; 275) 'ref d ...{ .. }': &E
29[264; 275) 'E::A { .. }': E
30[278; 279) 'e': E
31[285; 286) 'd': &E
29 32
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_array.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_array.snap
index 3f2faa598..042248c35 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_array.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_array.snap
@@ -1,12 +1,12 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-30T20:08:05.185312835+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[9; 10) 'x': &str 7[9; 10) 'x': &str
8[18; 19) 'y': isize 8[18; 19) 'y': isize
9[28; 293) '{ ... []; }': () 9[28; 324) '{ ... 3]; }': ()
10[38; 39) 'a': [&str] 10[38; 39) 'a': [&str]
11[42; 45) '[x]': [&str] 11[42; 45) '[x]': [&str]
12[43; 44) 'x': &str 12[43; 44) 'x': &str
@@ -56,4 +56,10 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
56[260; 263) '"b"': &str 56[260; 263) '"b"': &str
57[275; 276) 'x': [u8] 57[275; 276) 'x': [u8]
58[288; 290) '[]': [u8] 58[288; 290) '[]': [u8]
59[300; 301) 'z': &[u8]
60[311; 321) '&[1, 2, 3]': &[u8]
61[312; 321) '[1, 2, 3]': [u8]
62[313; 314) '1': u8
63[316; 317) '2': u8
64[319; 320) '3': u8
59 65
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
index 5c74bd8c7..f5840a934 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-26T17:46:03.842478456+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[14; 15) 'x': u32 7[14; 15) 'x': u32
8[22; 24) '{}': () 8[22; 24) '{}': ()
@@ -10,7 +10,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
10[88; 89) 'a': u32 10[88; 89) 'a': u32
11[92; 108) 'unknow...nction': [unknown] 11[92; 108) 'unknow...nction': [unknown]
12[92; 110) 'unknow...tion()': u32 12[92; 110) 'unknow...tion()': u32
13[116; 125) 'takes_u32': fn(u32) -> () 13[116; 125) 'takes_u32': fn takes_u32(u32) -> ()
14[116; 128) 'takes_u32(a)': () 14[116; 128) 'takes_u32(a)': ()
15[126; 127) 'a': u32 15[126; 127) 'a': u32
16[138; 139) 'b': i32 16[138; 139) 'b': i32
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
index c506bcadd..b9dda2bc0 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-26T17:46:03.853259898+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[6; 7) 'x': bool 7[6; 7) 'x': bool
8[22; 34) '{ 0i32 }': i32 8[22; 34) '{ 0i32 }': i32
@@ -28,7 +28,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
28[174; 196) 'minus_...ONST_2': bool 28[174; 196) 'minus_...ONST_2': bool
29[189; 196) 'CONST_2': isize 29[189; 196) 'CONST_2': isize
30[206; 207) 'c': i32 30[206; 207) 'c': i32
31[210; 211) 'f': fn(bool) -> i32 31[210; 211) 'f': fn f(bool) -> i32
32[210; 219) 'f(z || y)': i32 32[210; 219) 'f(z || y)': i32
33[210; 223) 'f(z || y) + 5': i32 33[210; 223) 'f(z || y) + 5': i32
34[212; 213) 'z': bool 34[212; 213) 'z': bool
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
index 7203ad1e2..8ff6e55a6 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
@@ -1,21 +1,21 @@
1--- 1---
2created: "2019-01-22T14:44:59.954958500+00:00" 2created: "2019-01-26T18:16:16.530712344+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[10; 11) 't': [unknown] 7[10; 11) 't': [unknown]
8[21; 26) '{ t }': [unknown] 8[21; 26) '{ t }': [unknown]
9[23; 24) 't': [unknown] 9[23; 24) 't': [unknown]
10[38; 98) '{ ...(1); }': () 10[38; 98) '{ ...(1); }': ()
11[44; 46) 'id': fn(T) -> T 11[44; 46) 'id': fn id<u32>(T) -> T
12[44; 52) 'id(1u32)': T 12[44; 52) 'id(1u32)': u32
13[47; 51) '1u32': u32 13[47; 51) '1u32': u32
14[58; 68) 'id::<i128>': fn(T) -> T 14[58; 68) 'id::<i128>': fn id<i128>(T) -> T
15[58; 71) 'id::<i128>(1)': T 15[58; 71) 'id::<i128>(1)': i128
16[69; 70) '1': T 16[69; 70) '1': i128
17[81; 82) 'x': T 17[81; 82) 'x': u64
18[90; 92) 'id': fn(T) -> T 18[90; 92) 'id': fn id<u64>(T) -> T
19[90; 95) 'id(1)': T 19[90; 95) 'id(1)': u64
20[93; 94) '1': T 20[93; 94) '1': u64
21 21
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
index 4435180a1..f21bffa75 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.961936900+00:00" 2created: "2019-01-26T17:46:03.866825843+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[53; 57) 'self': A<[unknown]> 7[53; 57) 'self': A<[unknown]>
8[65; 87) '{ ... }': [unknown] 8[65; 87) '{ ... }': [unknown]
@@ -12,25 +12,25 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
12[110; 115) '{ t }': [unknown] 12[110; 115) '{ t }': [unknown]
13[112; 113) 't': [unknown] 13[112; 113) 't': [unknown]
14[135; 261) '{ ....x() }': i128 14[135; 261) '{ ....x() }': i128
15[146; 147) 'x': T 15[146; 147) 'x': i32
16[150; 151) '1': T 16[150; 151) '1': i32
17[162; 163) 'y': T 17[162; 163) 'y': i32
18[166; 168) 'id': fn(T) -> T 18[166; 168) 'id': fn id<i32>(T) -> T
19[166; 171) 'id(x)': T 19[166; 171) 'id(x)': i32
20[169; 170) 'x': T 20[169; 170) 'x': i32
21[182; 183) 'a': A<T> 21[182; 183) 'a': A<i32>
22[186; 200) 'A { x: id(y) }': A<T> 22[186; 200) 'A { x: id(y) }': A<i32>
23[193; 195) 'id': fn(T) -> T 23[193; 195) 'id': fn id<i32>(T) -> T
24[193; 198) 'id(y)': T 24[193; 198) 'id(y)': i32
25[196; 197) 'y': T 25[196; 197) 'y': i32
26[211; 212) 'z': T 26[211; 212) 'z': i32
27[215; 217) 'id': fn(T) -> T 27[215; 217) 'id': fn id<i32>(T) -> T
28[215; 222) 'id(a.x)': T 28[215; 222) 'id(a.x)': i32
29[218; 219) 'a': A<T> 29[218; 219) 'a': A<i32>
30[218; 221) 'a.x': T 30[218; 221) 'a.x': i32
31[233; 234) 'b': A<T> 31[233; 234) 'b': A<i32>
32[237; 247) 'A { x: z }': A<T> 32[237; 247) 'A { x: z }': A<i32>
33[244; 245) 'z': T 33[244; 245) 'z': i32
34[254; 255) 'b': A<T> 34[254; 255) 'b': A<i32>
35[254; 259) 'b.x()': i128 35[254; 259) 'b.x()': i128
36 36
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
index 0bceffaef..afbe2f747 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
@@ -1,16 +1,16 @@
1--- 1---
2created: "2019-01-22T14:44:59.975899500+00:00" 2created: "2019-01-26T17:46:03.928773630+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[15; 20) '{ 1 }': u32 7[15; 20) '{ 1 }': u32
8[17; 18) '1': u32 8[17; 18) '1': u32
9[48; 53) '{ 1 }': u32 9[48; 53) '{ 1 }': u32
10[50; 51) '1': u32 10[50; 51) '1': u32
11[67; 91) '{ ...c(); }': () 11[67; 91) '{ ...c(); }': ()
12[73; 74) 'a': fn() -> u32 12[73; 74) 'a': fn a() -> u32
13[73; 76) 'a()': u32 13[73; 76) 'a()': u32
14[82; 86) 'b::c': fn() -> u32 14[82; 86) 'b::c': fn c() -> u32
15[82; 88) 'b::c()': u32 15[82; 88) 'b::c()': u32
16 16
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap
new file mode 100644
index 000000000..a99323264
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap
@@ -0,0 +1,26 @@
1---
2created: "2019-01-27T16:54:18.368427685+00:00"
3creator: [email protected]
4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs
6---
7[10; 11) 'x': [unknown]
8[21; 30) '{ x }': [unknown]
9[27; 28) 'x': [unknown]
10[44; 45) 'x': &[unknown]
11[56; 65) '{ x }': &[unknown]
12[62; 63) 'x': &[unknown]
13[77; 157) '{ ...(1); }': ()
14[87; 88) 'y': u32
15[91; 96) '10u32': u32
16[102; 104) 'id': fn id<u32>(T) -> T
17[102; 107) 'id(y)': u32
18[105; 106) 'y': u32
19[117; 118) 'x': bool
20[127; 132) 'clone': fn clone<bool>(&T) -> T
21[127; 135) 'clone(z)': bool
22[133; 134) 'z': &bool
23[141; 151) 'id::<i128>': fn id<i128>(T) -> T
24[141; 154) 'id::<i128>(1)': i128
25[152; 153) '1': i128
26
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap
index 10aa61954..5021d0eeb 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap
@@ -1,11 +1,11 @@
1--- 1---
2created: "2019-01-22T14:45:00.059676600+00:00" 2created: "2019-01-28T14:51:16.185273502+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[27; 28) 'x': SomeType 7[27; 28) 'x': SomeType
8[40; 197) '{ ...lo"; }': () 8[40; 272) '{ ...lo"; }': ()
9[50; 51) 'b': bool 9[50; 51) 'b': bool
10[54; 59) 'false': bool 10[54; 59) 'false': bool
11[69; 70) 'c': bool 11[69; 70) 'c': bool
@@ -24,12 +24,25 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
24[147; 153) '!!true': bool 24[147; 153) '!!true': bool
25[148; 153) '!true': bool 25[148; 153) '!true': bool
26[149; 153) 'true': bool 26[149; 153) 'true': bool
27[159; 164) '-3.14': f64 27[163; 164) 'g': i32
28[160; 164) '3.14': f64 28[167; 170) '!42': i32
29[170; 172) '-x': [unknown] 29[168; 170) '42': i32
30[171; 172) 'x': SomeType 30[180; 181) 'h': u32
31[178; 180) '!x': [unknown] 31[184; 190) '!10u32': u32
32[179; 180) 'x': SomeType 32[185; 190) '10u32': u32
33[186; 194) '-"hello"': [unknown] 33[200; 201) 'j': i128
34[187; 194) '"hello"': &str 34[204; 206) '!a': i128
35[205; 206) 'a': i128
36[212; 217) '-3.14': f64
37[213; 217) '3.14': f64
38[223; 225) '!3': i32
39[224; 225) '3': i32
40[231; 233) '-x': [unknown]
41[232; 233) 'x': SomeType
42[239; 241) '!x': [unknown]
43[240; 241) 'x': SomeType
44[247; 255) '-"hello"': [unknown]
45[248; 255) '"hello"': &str
46[261; 269) '!"hello"': [unknown]
47[262; 269) '"hello"': &str
35 48
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f74d6f5ea..cb8d6351d 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -166,10 +166,15 @@ fn test(x: SomeType) {
166 let d: i128 = -a; 166 let d: i128 = -a;
167 let e = -100; 167 let e = -100;
168 let f = !!!true; 168 let f = !!!true;
169 let g = !42;
170 let h = !10u32;
171 let j = !a;
169 -3.14; 172 -3.14;
173 !3;
170 -x; 174 -x;
171 !x; 175 !x;
172 -"hello"; 176 -"hello";
177 !"hello";
173} 178}
174"#, 179"#,
175 ); 180 );
@@ -366,6 +371,7 @@ fn test(x: &str, y: isize) {
366 371
367 let b = [a, ["b"]]; 372 let b = [a, ["b"]];
368 let x: [u8; 0] = []; 373 let x: [u8; 0] = [];
374 let z: &[u8] = &[1, 2, 3];
369} 375}
370"#, 376"#,
371 ); 377 );
@@ -421,7 +427,8 @@ fn test() {
421 427
422 match e { 428 match e {
423 E::A { x } => x, 429 E::A { x } => x,
424 E::B => 1, 430 E::B if foo => 1,
431 E::B => 10,
425 }; 432 };
426 433
427 let ref d @ E::A { .. } = e; 434 let ref d @ E::A { .. } = e;
@@ -594,6 +601,29 @@ fn test() {
594 ); 601 );
595} 602}
596 603
604#[test]
605fn infer_type_param() {
606 check_inference(
607 "infer_type_param",
608 r#"
609fn id<T>(x: T) -> T {
610 x
611}
612
613fn clone<T>(x: &T) -> T {
614 x
615}
616
617fn test() {
618 let y = 10u32;
619 id(y);
620 let x: bool = clone(z);
621 id::<i128>(1);
622}
623"#,
624 );
625}
626
597fn infer(content: &str) -> String { 627fn infer(content: &str) -> String {
598 let (db, _, file_id) = MockDatabase::with_single_file(content); 628 let (db, _, file_id) = MockDatabase::with_single_file(content);
599 let source_file = db.parse(file_id); 629 let source_file = db.parse(file_id);
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml
index 79e473463..908899129 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide_api/Cargo.toml
@@ -15,6 +15,9 @@ rustc-hash = "1.0"
15parking_lot = "0.7.0" 15parking_lot = "0.7.0"
16unicase = "2.2.0" 16unicase = "2.2.0"
17 17
18jemallocator = { version = "0.1.9", optional = true }
19jemalloc-ctl = { version = "0.2.0", optional = true }
20
18ra_syntax = { path = "../ra_syntax" } 21ra_syntax = { path = "../ra_syntax" }
19ra_ide_api_light = { path = "../ra_ide_api_light" } 22ra_ide_api_light = { path = "../ra_ide_api_light" }
20ra_text_edit = { path = "../ra_text_edit" } 23ra_text_edit = { path = "../ra_text_edit" }
@@ -24,3 +27,6 @@ test_utils = { path = "../test_utils" }
24 27
25[dev-dependencies] 28[dev-dependencies]
26insta = "0.5.1" 29insta = "0.5.1"
30
31[features]
32jemalloc = [ "jemallocator", "jemalloc-ctl" ]
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index ee1e13799..2eb388e0e 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -3,9 +3,10 @@ use ra_db::SourceDatabase;
3use ra_syntax::{ 3use ra_syntax::{
4 AstNode, SyntaxNode, TextUnit, TextRange, 4 AstNode, SyntaxNode, TextUnit, TextRange,
5 SyntaxKind::FN_DEF, 5 SyntaxKind::FN_DEF,
6 ast::{self, ArgListOwner, DocCommentsOwner}, 6 ast::{self, ArgListOwner},
7 algo::find_node_at_offset, 7 algo::find_node_at_offset,
8}; 8};
9use hir::Docs;
9 10
10use crate::{FilePosition, CallInfo, db::RootDatabase}; 11use crate::{FilePosition, CallInfo, db::RootDatabase};
11 12
@@ -26,7 +27,9 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
26 let fn_file = db.parse(symbol.file_id); 27 let fn_file = db.parse(symbol.file_id);
27 let fn_def = symbol.ptr.to_node(&fn_file); 28 let fn_def = symbol.ptr.to_node(&fn_file);
28 let fn_def = ast::FnDef::cast(fn_def).unwrap(); 29 let fn_def = ast::FnDef::cast(fn_def).unwrap();
29 let mut call_info = CallInfo::new(fn_def)?; 30 let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?;
31
32 let mut call_info = CallInfo::new(db, function, fn_def)?;
30 // If we have a calling expression let's find which argument we are on 33 // If we have a calling expression let's find which argument we are on
31 let num_params = call_info.parameters.len(); 34 let num_params = call_info.parameters.len();
32 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); 35 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
@@ -110,46 +113,13 @@ impl<'a> FnCallNode<'a> {
110} 113}
111 114
112impl CallInfo { 115impl CallInfo {
113 fn new(node: &ast::FnDef) -> Option<Self> { 116 fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> {
114 let label: String = if let Some(body) = node.body() { 117 let label = crate::completion::function_label(node)?;
115 let body_range = body.syntax().range(); 118 let doc = function.docs(db);
116 let label: String = node
117 .syntax()
118 .children()
119 .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body
120 .filter(|child| ast::Comment::cast(child).is_none()) // Filter out doc comments
121 .map(|node| node.text().to_string())
122 .collect();
123 label
124 } else {
125 node.syntax().text().to_string()
126 };
127
128 let mut doc = None;
129 if let Some(docs) = node.doc_comment_text() {
130 // Massage markdown
131 let mut processed_lines = Vec::new();
132 let mut in_code_block = false;
133 for line in docs.lines() {
134 if line.starts_with("```") {
135 in_code_block = !in_code_block;
136 }
137
138 let line = if in_code_block && line.starts_with("```") && !line.contains("rust") {
139 "```rust".into()
140 } else {
141 line.to_string()
142 };
143
144 processed_lines.push(line);
145 }
146
147 doc = Some(processed_lines.join("\n"));
148 }
149 119
150 Some(CallInfo { 120 Some(CallInfo {
151 parameters: param_list(node), 121 parameters: param_list(node),
152 label: label.trim().to_owned(), 122 label,
153 doc, 123 doc,
154 active_parameter: None, 124 active_parameter: None,
155 }) 125 })
@@ -284,7 +254,7 @@ fn bar() {
284 assert_eq!(info.parameters, vec!["j".to_string()]); 254 assert_eq!(info.parameters, vec!["j".to_string()]);
285 assert_eq!(info.active_parameter, Some(0)); 255 assert_eq!(info.active_parameter, Some(0));
286 assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string()); 256 assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string());
287 assert_eq!(info.doc, Some("test".into())); 257 assert_eq!(info.doc.map(|it| it.into()), Some("test".to_string()));
288 } 258 }
289 259
290 #[test] 260 #[test]
@@ -313,18 +283,18 @@ pub fn do() {
313 assert_eq!(info.active_parameter, Some(0)); 283 assert_eq!(info.active_parameter, Some(0));
314 assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); 284 assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
315 assert_eq!( 285 assert_eq!(
316 info.doc, 286 info.doc.map(|it| it.into()),
317 Some( 287 Some(
318 r#"Adds one to the number given. 288 r#"Adds one to the number given.
319 289
320# Examples 290# Examples
321 291
322```rust 292```
323let five = 5; 293let five = 5;
324 294
325assert_eq!(6, my_crate::add_one(5)); 295assert_eq!(6, my_crate::add_one(5));
326```"# 296```"#
327 .into() 297 .to_string()
328 ) 298 )
329 ); 299 );
330 } 300 }
@@ -359,18 +329,18 @@ pub fn do_it() {
359 assert_eq!(info.active_parameter, Some(0)); 329 assert_eq!(info.active_parameter, Some(0));
360 assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string()); 330 assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
361 assert_eq!( 331 assert_eq!(
362 info.doc, 332 info.doc.map(|it| it.into()),
363 Some( 333 Some(
364 r#"Adds one to the number given. 334 r#"Adds one to the number given.
365 335
366# Examples 336# Examples
367 337
368```rust 338```
369let five = 5; 339let five = 5;
370 340
371assert_eq!(6, my_crate::add_one(5)); 341assert_eq!(6, my_crate::add_one(5));
372```"# 342```"#
373 .into() 343 .to_string()
374 ) 344 )
375 ); 345 );
376 } 346 }
@@ -414,12 +384,12 @@ pub fn foo() {
414 ); 384 );
415 assert_eq!(info.active_parameter, Some(1)); 385 assert_eq!(info.active_parameter, Some(1));
416 assert_eq!( 386 assert_eq!(
417 info.doc, 387 info.doc.map(|it| it.into()),
418 Some( 388 Some(
419 r#"Method is called when writer finishes. 389 r#"Method is called when writer finishes.
420 390
421By default this method stops actor's `Context`."# 391By default this method stops actor's `Context`."#
422 .into() 392 .to_string()
423 ) 393 )
424 ); 394 );
425 } 395 }
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index b1867de42..722d94f3a 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -10,6 +10,7 @@ mod complete_scope;
10mod complete_postfix; 10mod complete_postfix;
11 11
12use ra_db::SourceDatabase; 12use ra_db::SourceDatabase;
13use ra_syntax::ast::{self, AstNode};
13 14
14use crate::{ 15use crate::{
15 db, 16 db,
@@ -61,3 +62,21 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
61 complete_postfix::complete_postfix(&mut acc, &ctx); 62 complete_postfix::complete_postfix(&mut acc, &ctx);
62 Some(acc) 63 Some(acc)
63} 64}
65
66pub fn function_label(node: &ast::FnDef) -> Option<String> {
67 let label: String = if let Some(body) = node.body() {
68 let body_range = body.syntax().range();
69 let label: String = node
70 .syntax()
71 .children()
72 .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body
73 .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments
74 .map(|node| node.text().to_string())
75 .collect();
76 label
77 } else {
78 node.syntax().text().to_string()
79 };
80
81 Some(label.trim().to_owned())
82}
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index b16ac2b28..d3bc14894 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -1,12 +1,12 @@
1use hir::{Docs, Documentation}; 1use hir::{Docs, Documentation};
2use ra_syntax::{ 2use ra_syntax::TextRange;
3 ast::{self, AstNode},
4 TextRange,
5};
6use ra_text_edit::TextEdit; 3use ra_text_edit::TextEdit;
7use test_utils::tested_by; 4use test_utils::tested_by;
8 5
9use crate::completion::completion_context::CompletionContext; 6use crate::completion::{
7 completion_context::CompletionContext,
8 function_label,
9};
10 10
11/// `CompletionItem` describes a single completion variant in the editor pop-up. 11/// `CompletionItem` describes a single completion variant in the editor pop-up.
12/// It is basically a POD with various properties. To construct a 12/// It is basically a POD with various properties. To construct a
@@ -97,8 +97,8 @@ impl CompletionItem {
97 self.detail.as_ref().map(|it| it.as_str()) 97 self.detail.as_ref().map(|it| it.as_str())
98 } 98 }
99 /// A doc-comment 99 /// A doc-comment
100 pub fn documentation(&self) -> Option<&str> { 100 pub fn documentation(&self) -> Option<Documentation> {
101 self.documentation.as_ref().map(|it| it.contents()) 101 self.documentation.clone()
102 } 102 }
103 /// What string is used for filtering. 103 /// What string is used for filtering.
104 pub fn lookup(&self) -> &str { 104 pub fn lookup(&self) -> &str {
@@ -252,7 +252,7 @@ impl Builder {
252 self.documentation = Some(docs); 252 self.documentation = Some(docs);
253 } 253 }
254 254
255 if let Some(label) = function_label(ctx, function) { 255 if let Some(label) = function_item_label(ctx, function) {
256 self.detail = Some(label); 256 self.detail = Some(label);
257 } 257 }
258 258
@@ -292,24 +292,9 @@ impl Into<Vec<CompletionItem>> for Completions {
292 } 292 }
293} 293}
294 294
295fn function_label(ctx: &CompletionContext, function: hir::Function) -> Option<String> { 295fn function_item_label(ctx: &CompletionContext, function: hir::Function) -> Option<String> {
296 let node = function.source(ctx.db).1; 296 let node = function.source(ctx.db).1;
297 297 function_label(&node)
298 let label: String = if let Some(body) = node.body() {
299 let body_range = body.syntax().range();
300 let label: String = node
301 .syntax()
302 .children()
303 .filter(|child| !child.range().is_subrange(&body_range)) // Filter out body
304 .filter(|child| ast::Comment::cast(child).is_none()) // Filter out comments
305 .map(|node| node.text().to_string())
306 .collect();
307 label
308 } else {
309 node.syntax().text().to_string()
310 };
311
312 Some(label.trim().to_owned())
313} 298}
314 299
315#[cfg(test)] 300#[cfg(test)]
@@ -324,10 +309,11 @@ pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind
324 }; 309 };
325 let completions = completions(&analysis.db, position).unwrap(); 310 let completions = completions(&analysis.db, position).unwrap();
326 let completion_items: Vec<CompletionItem> = completions.into(); 311 let completion_items: Vec<CompletionItem> = completions.into();
327 let kind_completions: Vec<CompletionItem> = completion_items 312 let mut kind_completions: Vec<CompletionItem> = completion_items
328 .into_iter() 313 .into_iter()
329 .filter(|c| c.completion_kind == kind) 314 .filter(|c| c.completion_kind == kind)
330 .collect(); 315 .collect();
316 kind_completions.sort_by_key(|c| c.label.clone());
331 assert_debug_snapshot_matches!(test_name, kind_completions); 317 assert_debug_snapshot_matches!(test_name, kind_completions);
332} 318}
333 319
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap
index 329309c90..31df6565b 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap
@@ -1,26 +1,12 @@
1--- 1---
2created: "2019-01-23T07:42:59.656273+00:00" 2created: "2019-01-27T19:56:59.944446814+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "x",
11 kind: Some(
12 Binding
13 ),
14 detail: None,
15 documentation: None,
16 lookup: None,
17 insert_text: None,
18 insert_text_format: PlainText,
19 source_range: [83; 83),
20 text_edit: None
21 },
22 CompletionItem {
23 completion_kind: Reference,
24 label: "quux", 10 label: "quux",
25 kind: Some( 11 kind: Some(
26 Function 12 Function
@@ -36,5 +22,19 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
36 insert_text_format: Snippet, 22 insert_text_format: Snippet,
37 source_range: [83; 83), 23 source_range: [83; 83),
38 text_edit: None 24 text_edit: None
25 },
26 CompletionItem {
27 completion_kind: Reference,
28 label: "x",
29 kind: Some(
30 Binding
31 ),
32 detail: None,
33 documentation: None,
34 lookup: None,
35 insert_text: None,
36 insert_text_format: PlainText,
37 source_range: [83; 83),
38 text_edit: None
39 } 39 }
40] 40]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap
index dbbe06c7b..9f37bae36 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap
@@ -1,13 +1,13 @@
1--- 1---
2created: "2019-01-23T07:42:59.658419+00:00" 2created: "2019-01-27T19:56:59.946956414+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "b", 10 label: "a",
11 kind: Some( 11 kind: Some(
12 Binding 12 Binding
13 ), 13 ),
@@ -21,7 +21,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
21 }, 21 },
22 CompletionItem { 22 CompletionItem {
23 completion_kind: Reference, 23 completion_kind: Reference,
24 label: "a", 24 label: "b",
25 kind: Some( 25 kind: Some(
26 Binding 26 Binding
27 ), 27 ),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap
index b727bb70c..f4808bc93 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap
@@ -1,21 +1,25 @@
1--- 1---
2created: "2019-01-23T07:42:59.657713+00:00" 2created: "2019-01-27T19:56:59.948953759+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "y", 10 label: "quux",
11 kind: Some( 11 kind: Some(
12 Binding 12 Function
13 ),
14 detail: Some(
15 "fn quux(x: i32)"
13 ), 16 ),
14 detail: None,
15 documentation: None, 17 documentation: None,
16 lookup: None, 18 lookup: None,
17 insert_text: None, 19 insert_text: Some(
18 insert_text_format: PlainText, 20 "quux($0)"
21 ),
22 insert_text_format: Snippet,
19 source_range: [79; 79), 23 source_range: [79; 79),
20 text_edit: None 24 text_edit: None
21 }, 25 },
@@ -35,19 +39,15 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
35 }, 39 },
36 CompletionItem { 40 CompletionItem {
37 completion_kind: Reference, 41 completion_kind: Reference,
38 label: "quux", 42 label: "y",
39 kind: Some( 43 kind: Some(
40 Function 44 Binding
41 ),
42 detail: Some(
43 "fn quux(x: i32)"
44 ), 45 ),
46 detail: None,
45 documentation: None, 47 documentation: None,
46 lookup: None, 48 lookup: None,
47 insert_text: Some( 49 insert_text: None,
48 "quux($0)" 50 insert_text_format: PlainText,
49 ),
50 insert_text_format: Snippet,
51 source_range: [79; 79), 51 source_range: [79; 79),
52 text_edit: None 52 text_edit: None
53 } 53 }
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap
index 8dcb773d0..25ccbdb8f 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap
@@ -1,13 +1,13 @@
1--- 1---
2created: "2019-01-23T05:27:32.197434+00:00" 2created: "2019-01-27T19:56:59.913816522+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Keyword, 9 completion_kind: Keyword,
10 label: "if", 10 label: "break",
11 kind: Some( 11 kind: Some(
12 Keyword 12 Keyword
13 ), 13 ),
@@ -15,7 +15,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
15 documentation: None, 15 documentation: None,
16 lookup: None, 16 lookup: None,
17 insert_text: Some( 17 insert_text: Some(
18 "if $0 {}" 18 "break;"
19 ), 19 ),
20 insert_text_format: Snippet, 20 insert_text_format: Snippet,
21 source_range: [55; 55), 21 source_range: [55; 55),
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "continue",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "continue;"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [55; 55), 37 source_range: [55; 55),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "if",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "if $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [55; 55), 53 source_range: [55; 55),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "continue", 74 label: "match",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "continue;" 82 "match $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [55; 55), 85 source_range: [55; 55),
@@ -87,7 +87,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
87 }, 87 },
88 CompletionItem { 88 CompletionItem {
89 completion_kind: Keyword, 89 completion_kind: Keyword,
90 label: "break", 90 label: "return",
91 kind: Some( 91 kind: Some(
92 Keyword 92 Keyword
93 ), 93 ),
@@ -95,7 +95,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
95 documentation: None, 95 documentation: None,
96 lookup: None, 96 lookup: None,
97 insert_text: Some( 97 insert_text: Some(
98 "break;" 98 "return $0;"
99 ), 99 ),
100 insert_text_format: Snippet, 100 insert_text_format: Snippet,
101 source_range: [55; 55), 101 source_range: [55; 55),
@@ -103,7 +103,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
103 }, 103 },
104 CompletionItem { 104 CompletionItem {
105 completion_kind: Keyword, 105 completion_kind: Keyword,
106 label: "return", 106 label: "while",
107 kind: Some( 107 kind: Some(
108 Keyword 108 Keyword
109 ), 109 ),
@@ -111,7 +111,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
111 documentation: None, 111 documentation: None,
112 lookup: None, 112 lookup: None,
113 insert_text: Some( 113 insert_text: Some(
114 "return $0;" 114 "while $0 {}"
115 ), 115 ),
116 insert_text_format: Snippet, 116 insert_text_format: Snippet,
117 source_range: [55; 55), 117 source_range: [55; 55),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap
index 1c64c6548..42a888e3a 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.314513+00:00" 2created: "2019-01-27T20:00:15.602646258+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [60; 60), 37 source_range: [60; 60),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [60; 60), 53 source_range: [60; 60),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return $0;"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [60; 60), 69 source_range: [60; 60),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return $0;" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [60; 60), 85 source_range: [60; 60),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap
index 8c9657b5c..5e4ff6af8 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.197678+00:00" 2created: "2019-01-27T19:56:59.920190685+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [85; 85), 37 source_range: [85; 85),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [85; 85), 53 source_range: [85; 85),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return $0"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [85; 85), 69 source_range: [85; 85),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return $0" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [85; 85), 85 source_range: [85; 85),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap
index 091bf581e..f4a04ecb3 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap
@@ -1,18 +1,18 @@
1--- 1---
2created: "2019-01-22T15:38:19.788294+00:00" 2created: "2019-01-27T19:56:59.965130040+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "main", 10 label: "frobnicate",
11 kind: Some( 11 kind: Some(
12 Function 12 Function
13 ), 13 ),
14 detail: Some( 14 detail: Some(
15 "fn main()" 15 "fn frobnicate()"
16 ), 16 ),
17 documentation: None, 17 documentation: None,
18 lookup: None, 18 lookup: None,
@@ -23,12 +23,12 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Reference, 25 completion_kind: Reference,
26 label: "frobnicate", 26 label: "main",
27 kind: Some( 27 kind: Some(
28 Function 28 Function
29 ), 29 ),
30 detail: Some( 30 detail: Some(
31 "fn frobnicate()" 31 "fn main()"
32 ), 32 ),
33 documentation: None, 33 documentation: None,
34 lookup: None, 34 lookup: None,
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap
index 8c84439b2..8ac58006e 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant.snap
@@ -1,5 +1,5 @@
1--- 1---
2created: "2019-01-25T16:44:04.640545300+00:00" 2created: "2019-01-27T19:56:59.937030324+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
@@ -7,16 +7,16 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "Foo", 10 label: "Bar",
11 kind: Some( 11 kind: Some(
12 EnumVariant 12 EnumVariant
13 ), 13 ),
14 detail: Some( 14 detail: Some(
15 "()" 15 "(i32)"
16 ), 16 ),
17 documentation: Some( 17 documentation: Some(
18 Documentation( 18 Documentation(
19 "Foo Variant" 19 "Bar Variant with i32"
20 ) 20 )
21 ), 21 ),
22 lookup: None, 22 lookup: None,
@@ -27,16 +27,16 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
27 }, 27 },
28 CompletionItem { 28 CompletionItem {
29 completion_kind: Reference, 29 completion_kind: Reference,
30 label: "Bar", 30 label: "Foo",
31 kind: Some( 31 kind: Some(
32 EnumVariant 32 EnumVariant
33 ), 33 ),
34 detail: Some( 34 detail: Some(
35 "(i32)" 35 "()"
36 ), 36 ),
37 documentation: Some( 37 documentation: Some(
38 Documentation( 38 Documentation(
39 "Bar Variant with i32" 39 "Foo Variant"
40 ) 40 )
41 ), 41 ),
42 lookup: None, 42 lookup: None,
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap
index 384634517..9fd2d81ec 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__enum_variant_with_details.snap
@@ -1,5 +1,5 @@
1--- 1---
2created: "2019-01-25T16:44:04.641542400+00:00" 2created: "2019-01-27T19:56:59.938973454+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
@@ -7,16 +7,16 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "Foo", 10 label: "Bar",
11 kind: Some( 11 kind: Some(
12 EnumVariant 12 EnumVariant
13 ), 13 ),
14 detail: Some( 14 detail: Some(
15 "()" 15 "(i32, u32)"
16 ), 16 ),
17 documentation: Some( 17 documentation: Some(
18 Documentation( 18 Documentation(
19 "Foo Variant (empty)" 19 "Bar Variant with i32 and u32"
20 ) 20 )
21 ), 21 ),
22 lookup: None, 22 lookup: None,
@@ -27,16 +27,16 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
27 }, 27 },
28 CompletionItem { 28 CompletionItem {
29 completion_kind: Reference, 29 completion_kind: Reference,
30 label: "Bar", 30 label: "Foo",
31 kind: Some( 31 kind: Some(
32 EnumVariant 32 EnumVariant
33 ), 33 ),
34 detail: Some( 34 detail: Some(
35 "(i32, u32)" 35 "()"
36 ), 36 ),
37 documentation: Some( 37 documentation: Some(
38 Documentation( 38 Documentation(
39 "Bar Variant with i32 and u32" 39 "Foo Variant (empty)"
40 ) 40 )
41 ), 41 ),
42 lookup: None, 42 lookup: None,
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion1.snap
index 13f915446..6b2287951 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion1.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion1.snap
@@ -1,19 +1,19 @@
1--- 1---
2created: "2019-01-22T14:45:00.817649800+00:00" 2created: "2019-01-27T19:56:59.944118550+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Postfix, 9 completion_kind: Postfix,
10 label: "not", 10 label: "if",
11 kind: None, 11 kind: None,
12 detail: None, 12 detail: None,
13 documentation: None, 13 documentation: None,
14 lookup: None, 14 lookup: None,
15 insert_text: Some( 15 insert_text: Some(
16 "!bar" 16 "if bar {$0}"
17 ), 17 ),
18 insert_text_format: Snippet, 18 insert_text_format: Snippet,
19 source_range: [76; 76), 19 source_range: [76; 76),
@@ -30,13 +30,13 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
30 }, 30 },
31 CompletionItem { 31 CompletionItem {
32 completion_kind: Postfix, 32 completion_kind: Postfix,
33 label: "if", 33 label: "match",
34 kind: None, 34 kind: None,
35 detail: None, 35 detail: None,
36 documentation: None, 36 documentation: None,
37 lookup: None, 37 lookup: None,
38 insert_text: Some( 38 insert_text: Some(
39 "if bar {$0}" 39 "match bar {\n${1:_} => {$0\\},\n}"
40 ), 40 ),
41 insert_text_format: Snippet, 41 insert_text_format: Snippet,
42 source_range: [76; 76), 42 source_range: [76; 76),
@@ -53,13 +53,13 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
53 }, 53 },
54 CompletionItem { 54 CompletionItem {
55 completion_kind: Postfix, 55 completion_kind: Postfix,
56 label: "match", 56 label: "not",
57 kind: None, 57 kind: None,
58 detail: None, 58 detail: None,
59 documentation: None, 59 documentation: None,
60 lookup: None, 60 lookup: None,
61 insert_text: Some( 61 insert_text: Some(
62 "match bar {\n${1:_} => {$0\\},\n}" 62 "!bar"
63 ), 63 ),
64 insert_text_format: Snippet, 64 insert_text_format: Snippet,
65 source_range: [76; 76), 65 source_range: [76; 76),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion2.snap
index fff87574d..6925fd102 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion2.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion2.snap
@@ -1,19 +1,19 @@
1--- 1---
2created: "2019-01-22T14:45:00.820642200+00:00" 2created: "2019-01-27T19:56:59.942831213+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Postfix, 9 completion_kind: Postfix,
10 label: "not", 10 label: "if",
11 kind: None, 11 kind: None,
12 detail: None, 12 detail: None,
13 documentation: None, 13 documentation: None,
14 lookup: None, 14 lookup: None,
15 insert_text: Some( 15 insert_text: Some(
16 "!bar" 16 "if bar {$0}"
17 ), 17 ),
18 insert_text_format: Snippet, 18 insert_text_format: Snippet,
19 source_range: [76; 77), 19 source_range: [76; 77),
@@ -30,13 +30,13 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
30 }, 30 },
31 CompletionItem { 31 CompletionItem {
32 completion_kind: Postfix, 32 completion_kind: Postfix,
33 label: "if", 33 label: "match",
34 kind: None, 34 kind: None,
35 detail: None, 35 detail: None,
36 documentation: None, 36 documentation: None,
37 lookup: None, 37 lookup: None,
38 insert_text: Some( 38 insert_text: Some(
39 "if bar {$0}" 39 "match bar {\n${1:_} => {$0\\},\n}"
40 ), 40 ),
41 insert_text_format: Snippet, 41 insert_text_format: Snippet,
42 source_range: [76; 77), 42 source_range: [76; 77),
@@ -53,13 +53,13 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
53 }, 53 },
54 CompletionItem { 54 CompletionItem {
55 completion_kind: Postfix, 55 completion_kind: Postfix,
56 label: "match", 56 label: "not",
57 kind: None, 57 kind: None,
58 detail: None, 58 detail: None,
59 documentation: None, 59 documentation: None,
60 lookup: None, 60 lookup: None,
61 insert_text: Some( 61 insert_text: Some(
62 "match bar {\n${1:_} => {$0\\},\n}" 62 "!bar"
63 ), 63 ),
64 insert_text_format: Snippet, 64 insert_text_format: Snippet,
65 source_range: [76; 77), 65 source_range: [76; 77),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion3.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion3.snap
index e0f4730e7..22eaf2b4f 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion3.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__filter_postfix_completion3.snap
@@ -1,19 +1,19 @@
1--- 1---
2created: "2019-01-23T05:27:32.222118+00:00" 2created: "2019-01-27T19:56:59.944615925+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Postfix, 9 completion_kind: Postfix,
10 label: "not", 10 label: "if",
11 kind: None, 11 kind: None,
12 detail: None, 12 detail: None,
13 documentation: None, 13 documentation: None,
14 lookup: None, 14 lookup: None,
15 insert_text: Some( 15 insert_text: Some(
16 "!bar" 16 "if bar {$0}"
17 ), 17 ),
18 insert_text_format: Snippet, 18 insert_text_format: Snippet,
19 source_range: [78; 78), 19 source_range: [78; 78),
@@ -30,13 +30,13 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
30 }, 30 },
31 CompletionItem { 31 CompletionItem {
32 completion_kind: Postfix, 32 completion_kind: Postfix,
33 label: "if", 33 label: "match",
34 kind: None, 34 kind: None,
35 detail: None, 35 detail: None,
36 documentation: None, 36 documentation: None,
37 lookup: None, 37 lookup: None,
38 insert_text: Some( 38 insert_text: Some(
39 "if bar {$0}" 39 "match bar {\n${1:_} => {$0\\},\n}"
40 ), 40 ),
41 insert_text_format: Snippet, 41 insert_text_format: Snippet,
42 source_range: [78; 78), 42 source_range: [78; 78),
@@ -53,13 +53,13 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
53 }, 53 },
54 CompletionItem { 54 CompletionItem {
55 completion_kind: Postfix, 55 completion_kind: Postfix,
56 label: "match", 56 label: "not",
57 kind: None, 57 kind: None,
58 detail: None, 58 detail: None,
59 documentation: None, 59 documentation: None,
60 lookup: None, 60 lookup: None,
61 insert_text: Some( 61 insert_text: Some(
62 "match bar {\n${1:_} => {$0\\},\n}" 62 "!bar"
63 ), 63 ),
64 insert_text_format: Snippet, 64 insert_text_format: Snippet,
65 source_range: [78; 78), 65 source_range: [78; 78),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap
index b30a4c9e9..339df3c84 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap
@@ -1,23 +1,23 @@
1--- 1---
2created: "2019-01-22T15:38:19.919937+00:00" 2created: "2019-01-27T19:56:59.965550827+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "no_args", 10 label: "main",
11 kind: Some( 11 kind: Some(
12 Function 12 Function
13 ), 13 ),
14 detail: Some( 14 detail: Some(
15 "fn no_args()" 15 "fn main()"
16 ), 16 ),
17 documentation: None, 17 documentation: None,
18 lookup: None, 18 lookup: None,
19 insert_text: Some( 19 insert_text: Some(
20 "no_args()$0" 20 "main()$0"
21 ), 21 ),
22 insert_text_format: Snippet, 22 insert_text_format: Snippet,
23 source_range: [53; 56), 23 source_range: [53; 56),
@@ -25,17 +25,17 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
25 }, 25 },
26 CompletionItem { 26 CompletionItem {
27 completion_kind: Reference, 27 completion_kind: Reference,
28 label: "main", 28 label: "no_args",
29 kind: Some( 29 kind: Some(
30 Function 30 Function
31 ), 31 ),
32 detail: Some( 32 detail: Some(
33 "fn main()" 33 "fn no_args()"
34 ), 34 ),
35 documentation: None, 35 documentation: None,
36 lookup: None, 36 lookup: None,
37 insert_text: Some( 37 insert_text: Some(
38 "main()$0" 38 "no_args()$0"
39 ), 39 ),
40 insert_text_format: Snippet, 40 insert_text_format: Snippet,
41 source_range: [53; 56), 41 source_range: [53; 56),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap
index 2b6182578..874c41a02 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.197298+00:00" 2created: "2019-01-27T19:56:59.913826978+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [41; 41), 37 source_range: [41; 41),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [41; 41), 53 source_range: [41; 41),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return;"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [41; 41), 69 source_range: [41; 41),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return;" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [41; 41), 85 source_range: [41; 41),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap
index a56105f0c..0eec578be 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap
@@ -1,13 +1,13 @@
1--- 1---
2created: "2019-01-23T05:27:32.197423+00:00" 2created: "2019-01-27T19:56:59.914744437+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Keyword, 9 completion_kind: Keyword,
10 label: "if", 10 label: "else",
11 kind: Some( 11 kind: Some(
12 Keyword 12 Keyword
13 ), 13 ),
@@ -15,7 +15,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
15 documentation: None, 15 documentation: None,
16 lookup: None, 16 lookup: None,
17 insert_text: Some( 17 insert_text: Some(
18 "if $0 {}" 18 "else {$0}"
19 ), 19 ),
20 insert_text_format: Snippet, 20 insert_text_format: Snippet,
21 source_range: [92; 92), 21 source_range: [92; 92),
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "else if",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "else if $0 {}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [92; 92), 37 source_range: [92; 92),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "if",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "if $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [92; 92), 53 source_range: [92; 92),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "else", 74 label: "match",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "else {$0}" 82 "match $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [92; 92), 85 source_range: [92; 92),
@@ -87,7 +87,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
87 }, 87 },
88 CompletionItem { 88 CompletionItem {
89 completion_kind: Keyword, 89 completion_kind: Keyword,
90 label: "else if", 90 label: "return",
91 kind: Some( 91 kind: Some(
92 Keyword 92 Keyword
93 ), 93 ),
@@ -95,7 +95,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
95 documentation: None, 95 documentation: None,
96 lookup: None, 96 lookup: None,
97 insert_text: Some( 97 insert_text: Some(
98 "else if $0 {}" 98 "return;"
99 ), 99 ),
100 insert_text_format: Snippet, 100 insert_text_format: Snippet,
101 source_range: [92; 92), 101 source_range: [92; 92),
@@ -103,7 +103,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
103 }, 103 },
104 CompletionItem { 104 CompletionItem {
105 completion_kind: Keyword, 105 completion_kind: Keyword,
106 label: "return", 106 label: "while",
107 kind: Some( 107 kind: Some(
108 Keyword 108 Keyword
109 ), 109 ),
@@ -111,7 +111,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
111 documentation: None, 111 documentation: None,
112 lookup: None, 112 lookup: None,
113 insert_text: Some( 113 insert_text: Some(
114 "return;" 114 "while $0 {}"
115 ), 115 ),
116 insert_text_format: Snippet, 116 insert_text_format: Snippet,
117 source_range: [92; 92), 117 source_range: [92; 92),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap
index 84efab6f6..4b99f15e1 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.200056+00:00" 2created: "2019-01-27T19:56:59.927994050+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [48; 48), 37 source_range: [48; 48),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [48; 48), 53 source_range: [48; 48),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return $0;"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [48; 48), 69 source_range: [48; 48),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return $0;" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [48; 48), 85 source_range: [48; 48),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap
index 8b254ce99..f8587f147 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.314468+00:00" 2created: "2019-01-27T20:00:15.604538211+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [41; 41), 37 source_range: [41; 41),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [41; 41), 53 source_range: [41; 41),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return;"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [41; 41), 69 source_range: [41; 41),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return;" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [41; 41), 85 source_range: [41; 41),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap
index d36b555db..3c27e079f 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.197624+00:00" 2created: "2019-01-27T19:56:59.918882346+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [83; 83), 37 source_range: [83; 83),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [83; 83), 53 source_range: [83; 83),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return $0;"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [83; 83), 69 source_range: [83; 83),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return $0;" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [83; 83), 85 source_range: [83; 83),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap
index d74483c0b..d1be8c6e7 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-23T05:27:32.302452+00:00" 2created: "2019-01-27T20:00:15.604282112+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
@@ -23,7 +23,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "loop",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "loop {$0}"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [83; 83), 37 source_range: [83; 83),
@@ -39,7 +39,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "match",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "match $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [83; 83), 53 source_range: [83; 83),
@@ -55,7 +55,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
55 }, 55 },
56 CompletionItem { 56 CompletionItem {
57 completion_kind: Keyword, 57 completion_kind: Keyword,
58 label: "loop", 58 label: "return",
59 kind: Some( 59 kind: Some(
60 Keyword 60 Keyword
61 ), 61 ),
@@ -63,7 +63,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
63 documentation: None, 63 documentation: None,
64 lookup: None, 64 lookup: None,
65 insert_text: Some( 65 insert_text: Some(
66 "loop {$0}" 66 "return $0;"
67 ), 67 ),
68 insert_text_format: Snippet, 68 insert_text_format: Snippet,
69 source_range: [83; 83), 69 source_range: [83; 83),
@@ -71,7 +71,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "return", 74 label: "while",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "return $0;" 82 "while $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [83; 83), 85 source_range: [83; 83),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap
index a87880ab3..f6bba49ae 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap
@@ -1,25 +1,21 @@
1--- 1---
2created: "2019-01-23T07:42:59.657718+00:00" 2created: "2019-01-27T19:56:59.953151082+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "quux", 10 label: "Baz",
11 kind: Some( 11 kind: Some(
12 Function 12 Enum
13 ),
14 detail: Some(
15 "fn quux()"
16 ), 13 ),
14 detail: None,
17 documentation: None, 15 documentation: None,
18 lookup: None, 16 lookup: None,
19 insert_text: Some( 17 insert_text: None,
20 "quux()$0" 18 insert_text_format: PlainText,
21 ),
22 insert_text_format: Snippet,
23 source_range: [89; 89), 19 source_range: [89; 89),
24 text_edit: None 20 text_edit: None
25 }, 21 },
@@ -39,15 +35,19 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
39 }, 35 },
40 CompletionItem { 36 CompletionItem {
41 completion_kind: Reference, 37 completion_kind: Reference,
42 label: "Baz", 38 label: "quux",
43 kind: Some( 39 kind: Some(
44 Enum 40 Function
41 ),
42 detail: Some(
43 "fn quux()"
45 ), 44 ),
46 detail: None,
47 documentation: None, 45 documentation: None,
48 lookup: None, 46 lookup: None,
49 insert_text: None, 47 insert_text: Some(
50 insert_text_format: PlainText, 48 "quux()$0"
49 ),
50 insert_text_format: Snippet,
51 source_range: [89; 89), 51 source_range: [89; 89),
52 text_edit: None 52 text_edit: None
53 } 53 }
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap
index f95d10926..7c458664e 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap
@@ -1,39 +1,39 @@
1--- 1---
2created: "2019-01-23T07:42:59.657837+00:00" 2created: "2019-01-27T19:56:59.959185284+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "quux", 10 label: "Bar",
11 kind: Some( 11 kind: Some(
12 Function 12 Struct
13 ),
14 detail: Some(
15 "fn quux()"
16 ), 13 ),
14 detail: None,
17 documentation: None, 15 documentation: None,
18 lookup: None, 16 lookup: None,
19 insert_text: Some( 17 insert_text: None,
20 "quux()$0" 18 insert_text_format: PlainText,
21 ),
22 insert_text_format: Snippet,
23 source_range: [101; 101), 19 source_range: [101; 101),
24 text_edit: None 20 text_edit: None
25 }, 21 },
26 CompletionItem { 22 CompletionItem {
27 completion_kind: Reference, 23 completion_kind: Reference,
28 label: "Bar", 24 label: "quux",
29 kind: Some( 25 kind: Some(
30 Struct 26 Function
27 ),
28 detail: Some(
29 "fn quux()"
31 ), 30 ),
32 detail: None,
33 documentation: None, 31 documentation: None,
34 lookup: None, 32 lookup: None,
35 insert_text: None, 33 insert_text: Some(
36 insert_text_format: PlainText, 34 "quux()$0"
35 ),
36 insert_text_format: Snippet,
37 source_range: [101; 101), 37 source_range: [101; 101),
38 text_edit: None 38 text_edit: None
39 } 39 }
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap
index a5164b03e..5a35d9ca9 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap
@@ -1,13 +1,13 @@
1--- 1---
2created: "2019-01-22T14:45:00.651095300+00:00" 2created: "2019-01-27T19:56:59.922933445+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Keyword, 9 completion_kind: Keyword,
10 label: "if", 10 label: "break",
11 kind: Some( 11 kind: Some(
12 Keyword 12 Keyword
13 ), 13 ),
@@ -15,7 +15,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
15 documentation: None, 15 documentation: None,
16 lookup: None, 16 lookup: None,
17 insert_text: Some( 17 insert_text: Some(
18 "if $0 {}" 18 "break"
19 ), 19 ),
20 insert_text_format: Snippet, 20 insert_text_format: Snippet,
21 source_range: [106; 108), 21 source_range: [106; 108),
@@ -23,7 +23,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
23 }, 23 },
24 CompletionItem { 24 CompletionItem {
25 completion_kind: Keyword, 25 completion_kind: Keyword,
26 label: "match", 26 label: "continue",
27 kind: Some( 27 kind: Some(
28 Keyword 28 Keyword
29 ), 29 ),
@@ -31,7 +31,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
31 documentation: None, 31 documentation: None,
32 lookup: None, 32 lookup: None,
33 insert_text: Some( 33 insert_text: Some(
34 "match $0 {}" 34 "continue"
35 ), 35 ),
36 insert_text_format: Snippet, 36 insert_text_format: Snippet,
37 source_range: [106; 108), 37 source_range: [106; 108),
@@ -39,7 +39,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
39 }, 39 },
40 CompletionItem { 40 CompletionItem {
41 completion_kind: Keyword, 41 completion_kind: Keyword,
42 label: "while", 42 label: "if",
43 kind: Some( 43 kind: Some(
44 Keyword 44 Keyword
45 ), 45 ),
@@ -47,7 +47,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
47 documentation: None, 47 documentation: None,
48 lookup: None, 48 lookup: None,
49 insert_text: Some( 49 insert_text: Some(
50 "while $0 {}" 50 "if $0 {}"
51 ), 51 ),
52 insert_text_format: Snippet, 52 insert_text_format: Snippet,
53 source_range: [106; 108), 53 source_range: [106; 108),
@@ -71,7 +71,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
71 }, 71 },
72 CompletionItem { 72 CompletionItem {
73 completion_kind: Keyword, 73 completion_kind: Keyword,
74 label: "continue", 74 label: "match",
75 kind: Some( 75 kind: Some(
76 Keyword 76 Keyword
77 ), 77 ),
@@ -79,7 +79,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
79 documentation: None, 79 documentation: None,
80 lookup: None, 80 lookup: None,
81 insert_text: Some( 81 insert_text: Some(
82 "continue" 82 "match $0 {}"
83 ), 83 ),
84 insert_text_format: Snippet, 84 insert_text_format: Snippet,
85 source_range: [106; 108), 85 source_range: [106; 108),
@@ -87,7 +87,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
87 }, 87 },
88 CompletionItem { 88 CompletionItem {
89 completion_kind: Keyword, 89 completion_kind: Keyword,
90 label: "break", 90 label: "return",
91 kind: Some( 91 kind: Some(
92 Keyword 92 Keyword
93 ), 93 ),
@@ -95,7 +95,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
95 documentation: None, 95 documentation: None,
96 lookup: None, 96 lookup: None,
97 insert_text: Some( 97 insert_text: Some(
98 "break" 98 "return"
99 ), 99 ),
100 insert_text_format: Snippet, 100 insert_text_format: Snippet,
101 source_range: [106; 108), 101 source_range: [106; 108),
@@ -103,7 +103,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
103 }, 103 },
104 CompletionItem { 104 CompletionItem {
105 completion_kind: Keyword, 105 completion_kind: Keyword,
106 label: "return", 106 label: "while",
107 kind: Some( 107 kind: Some(
108 Keyword 108 Keyword
109 ), 109 ),
@@ -111,7 +111,7 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
111 documentation: None, 111 documentation: None,
112 lookup: None, 112 lookup: None,
113 insert_text: Some( 113 insert_text: Some(
114 "return" 114 "while $0 {}"
115 ), 115 ),
116 insert_text_format: Snippet, 116 insert_text_format: Snippet,
117 source_range: [106; 108), 117 source_range: [106; 108),
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap
index 5f5df0033..4d5c7a869 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap
@@ -1,5 +1,5 @@
1--- 1---
2created: "2019-01-23T13:19:23.501353210+00:00" 2created: "2019-01-27T19:56:59.910113268+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
@@ -7,35 +7,35 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "the_field", 10 label: "foo",
11 kind: Some( 11 kind: Some(
12 Field 12 Method
13 ), 13 ),
14 detail: Some( 14 detail: Some(
15 "(u32, i32)" 15 "fn foo(&self)"
16 ), 16 ),
17 documentation: None, 17 documentation: None,
18 lookup: None, 18 lookup: None,
19 insert_text: None, 19 insert_text: Some(
20 insert_text_format: PlainText, 20 "foo()$0"
21 ),
22 insert_text_format: Snippet,
21 source_range: [126; 126), 23 source_range: [126; 126),
22 text_edit: None 24 text_edit: None
23 }, 25 },
24 CompletionItem { 26 CompletionItem {
25 completion_kind: Reference, 27 completion_kind: Reference,
26 label: "foo", 28 label: "the_field",
27 kind: Some( 29 kind: Some(
28 Method 30 Field
29 ), 31 ),
30 detail: Some( 32 detail: Some(
31 "fn foo(&self)" 33 "(u32, i32)"
32 ), 34 ),
33 documentation: None, 35 documentation: None,
34 lookup: None, 36 lookup: None,
35 insert_text: Some( 37 insert_text: None,
36 "foo()$0" 38 insert_text_format: PlainText,
37 ),
38 insert_text_format: Snippet,
39 source_range: [126; 126), 39 source_range: [126; 126),
40 text_edit: None 40 text_edit: None
41 } 41 }
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap
index 580e92a90..1073d90fd 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap
@@ -1,5 +1,5 @@
1--- 1---
2created: "2019-01-25T19:27:09.519688600+00:00" 2created: "2019-01-27T19:56:59.909689544+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
@@ -7,39 +7,39 @@ source: crates/ra_ide_api/src/completion/completion_item.rs
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "the_field", 10 label: "foo",
11 kind: Some( 11 kind: Some(
12 Field 12 Method
13 ), 13 ),
14 detail: Some( 14 detail: Some(
15 "(u32,)" 15 "fn foo(self)"
16 ),
17 documentation: Some(
18 Documentation(
19 "This is the_field"
20 )
21 ), 16 ),
17 documentation: None,
22 lookup: None, 18 lookup: None,
23 insert_text: None, 19 insert_text: Some(
24 insert_text_format: PlainText, 20 "foo()$0"
21 ),
22 insert_text_format: Snippet,
25 source_range: [187; 187), 23 source_range: [187; 187),
26 text_edit: None 24 text_edit: None
27 }, 25 },
28 CompletionItem { 26 CompletionItem {
29 completion_kind: Reference, 27 completion_kind: Reference,
30 label: "foo", 28 label: "the_field",
31 kind: Some( 29 kind: Some(
32 Method 30 Field
33 ), 31 ),
34 detail: Some( 32 detail: Some(
35 "fn foo(self)" 33 "(u32,)"
36 ), 34 ),
37 documentation: None, 35 documentation: Some(
38 lookup: None, 36 Documentation(
39 insert_text: Some( 37 "This is the_field"
40 "foo()$0" 38 )
41 ), 39 ),
42 insert_text_format: Snippet, 40 lookup: None,
41 insert_text: None,
42 insert_text_format: PlainText,
43 source_range: [187; 187), 43 source_range: [187; 187),
44 text_edit: None 44 text_edit: None
45 } 45 }
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index 3da93ec35..6850811d7 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -1,4 +1,7 @@
1use std::sync::Arc; 1use std::{
2 sync::Arc,
3 time,
4};
2 5
3use ra_db::{ 6use ra_db::{
4 CheckCanceled, FileId, Canceled, SourceDatabase, 7 CheckCanceled, FileId, Canceled, SourceDatabase,
@@ -17,6 +20,8 @@ use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}};
17pub(crate) struct RootDatabase { 20pub(crate) struct RootDatabase {
18 runtime: salsa::Runtime<RootDatabase>, 21 runtime: salsa::Runtime<RootDatabase>,
19 interner: Arc<hir::HirInterner>, 22 interner: Arc<hir::HirInterner>,
23 pub(crate) last_gc: time::Instant,
24 pub(crate) last_gc_check: time::Instant,
20} 25}
21 26
22impl salsa::Database for RootDatabase { 27impl salsa::Database for RootDatabase {
@@ -33,6 +38,8 @@ impl Default for RootDatabase {
33 let mut db = RootDatabase { 38 let mut db = RootDatabase {
34 runtime: salsa::Runtime::default(), 39 runtime: salsa::Runtime::default(),
35 interner: Default::default(), 40 interner: Default::default(),
41 last_gc: time::Instant::now(),
42 last_gc_check: time::Instant::now(),
36 }; 43 };
37 db.set_crate_graph(Default::default()); 44 db.set_crate_graph(Default::default());
38 db.set_local_roots(Default::default()); 45 db.set_local_roots(Default::default());
@@ -46,6 +53,8 @@ impl salsa::ParallelDatabase for RootDatabase {
46 salsa::Snapshot::new(RootDatabase { 53 salsa::Snapshot::new(RootDatabase {
47 runtime: self.runtime.snapshot(self), 54 runtime: self.runtime.snapshot(self),
48 interner: Arc::clone(&self.interner), 55 interner: Arc::clone(&self.interner),
56 last_gc: self.last_gc.clone(),
57 last_gc_check: self.last_gc_check.clone(),
49 }) 58 })
50 } 59 }
51} 60}
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs
index 399433a01..31e0f5d6d 100644
--- a/crates/ra_ide_api/src/imp.rs
+++ b/crates/ra_ide_api/src/imp.rs
@@ -1,4 +1,7 @@
1use std::sync::Arc; 1use std::{
2 sync::Arc,
3 time,
4};
2 5
3use hir::{ 6use hir::{
4 self, Problem, source_binder 7 self, Problem, source_binder
@@ -19,12 +22,14 @@ use crate::{
19 CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, 22 CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit,
20 Query, RootChange, SourceChange, SourceFileEdit, 23 Query, RootChange, SourceChange, SourceFileEdit,
21 symbol_index::{FileSymbol, SymbolsDatabase}, 24 symbol_index::{FileSymbol, SymbolsDatabase},
25 status::syntax_tree_stats
22}; 26};
23 27
28const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
29
24impl db::RootDatabase { 30impl db::RootDatabase {
25 pub(crate) fn apply_change(&mut self, change: AnalysisChange) { 31 pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
26 log::info!("apply_change {:?}", change); 32 log::info!("apply_change {:?}", change);
27 // self.gc_syntax_trees();
28 if !change.new_roots.is_empty() { 33 if !change.new_roots.is_empty() {
29 let mut local_roots = Vec::clone(&self.local_roots()); 34 let mut local_roots = Vec::clone(&self.local_roots());
30 for (root_id, is_local) in change.new_roots { 35 for (root_id, is_local) in change.new_roots {
@@ -72,18 +77,36 @@ impl db::RootDatabase {
72 self.set_source_root(root_id, Arc::new(source_root)); 77 self.set_source_root(root_id, Arc::new(source_root));
73 } 78 }
74 79
75 /// Ideally, we should call this function from time to time to collect heavy 80 pub(crate) fn maybe_collect_garbage(&mut self) {
76 /// syntax trees. However, if we actually do that, everything is recomputed 81 if self.last_gc_check.elapsed() > GC_COOLDOWN {
77 /// for some reason. Needs investigation. 82 self.last_gc_check = time::Instant::now();
83 let retained_trees = syntax_tree_stats(self).retained;
84 if retained_trees > 100 {
85 log::info!(
86 "automatic garbadge collection, {} retained trees",
87 retained_trees
88 );
89 self.collect_garbage();
90 }
91 }
92 }
93
78 pub(crate) fn collect_garbage(&mut self) { 94 pub(crate) fn collect_garbage(&mut self) {
79 self.query(ra_db::ParseQuery) 95 self.last_gc = time::Instant::now();
80 .sweep(SweepStrategy::default().discard_values()); 96
81 self.query(hir::db::HirParseQuery) 97 let sweep = SweepStrategy::default()
82 .sweep(SweepStrategy::default().discard_values()); 98 .discard_values()
83 self.query(hir::db::FileItemsQuery) 99 .sweep_all_revisions();
84 .sweep(SweepStrategy::default().discard_values()); 100
85 self.query(hir::db::FileItemQuery) 101 self.query(ra_db::ParseQuery).sweep(sweep);
86 .sweep(SweepStrategy::default().discard_values()); 102
103 self.query(hir::db::HirParseQuery).sweep(sweep);
104 self.query(hir::db::FileItemsQuery).sweep(sweep);
105 self.query(hir::db::FileItemQuery).sweep(sweep);
106
107 self.query(hir::db::LowerModuleQuery).sweep(sweep);
108 self.query(hir::db::LowerModuleSourceMapQuery).sweep(sweep);
109 self.query(hir::db::BodySyntaxMappingQuery).sweep(sweep);
87 } 110 }
88} 111}
89 112
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
new file mode 100644
index 000000000..469d56d63
--- /dev/null
+++ b/crates/ra_ide_api/src/impls.rs
@@ -0,0 +1,120 @@
1use ra_db::{SourceDatabase};
2use ra_syntax::{
3 AstNode, ast,
4 algo::find_node_at_offset,
5};
6use hir::{db::HirDatabase, source_binder};
7
8use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
9
10pub(crate) fn goto_implementation(
11 db: &RootDatabase,
12 position: FilePosition,
13) -> Option<RangeInfo<Vec<NavigationTarget>>> {
14 let file = db.parse(position.file_id);
15 let syntax = file.syntax();
16
17 let module = source_binder::module_from_position(db, position)?;
18 let krate = module.krate(db)?;
19
20 let node = find_node_at_offset::<ast::NominalDef>(syntax, position.offset)?;
21 let ty = match node.kind() {
22 ast::NominalDefKind::StructDef(def) => {
23 source_binder::struct_from_module(db, module, &def).ty(db)
24 }
25 ast::NominalDefKind::EnumDef(def) => {
26 source_binder::enum_from_module(db, module, &def).ty(db)
27 }
28 };
29
30 let impls = db.impls_in_crate(krate);
31
32 let navs = impls
33 .lookup_impl_blocks(db, &ty)
34 .map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp));
35
36 Some(RangeInfo::new(node.syntax().range(), navs.collect()))
37}
38
39#[cfg(test)]
40mod tests {
41 use crate::mock_analysis::analysis_and_position;
42
43 fn check_goto(fixuture: &str, expected: &[&str]) {
44 let (analysis, pos) = analysis_and_position(fixuture);
45
46 let navs = analysis.goto_implementation(pos).unwrap().unwrap().info;
47 assert_eq!(navs.len(), expected.len());
48 navs.into_iter()
49 .enumerate()
50 .for_each(|(i, nav)| nav.assert_match(expected[i]));
51 }
52
53 #[test]
54 fn goto_implementation_works() {
55 check_goto(
56 "
57 //- /lib.rs
58 struct Foo<|>;
59 impl Foo {}
60 ",
61 &["impl IMPL_BLOCK FileId(1) [12; 23)"],
62 );
63 }
64
65 #[test]
66 fn goto_implementation_works_multiple_blocks() {
67 check_goto(
68 "
69 //- /lib.rs
70 struct Foo<|>;
71 impl Foo {}
72 impl Foo {}
73 ",
74 &[
75 "impl IMPL_BLOCK FileId(1) [12; 23)",
76 "impl IMPL_BLOCK FileId(1) [24; 35)",
77 ],
78 );
79 }
80
81 #[test]
82 fn goto_implementation_works_multiple_mods() {
83 check_goto(
84 "
85 //- /lib.rs
86 struct Foo<|>;
87 mod a {
88 impl super::Foo {}
89 }
90 mod b {
91 impl super::Foo {}
92 }
93 ",
94 &[
95 "impl IMPL_BLOCK FileId(1) [24; 42)",
96 "impl IMPL_BLOCK FileId(1) [57; 75)",
97 ],
98 );
99 }
100
101 #[test]
102 fn goto_implementation_works_multiple_files() {
103 check_goto(
104 "
105 //- /lib.rs
106 struct Foo<|>;
107 mod a;
108 mod b;
109 //- /a.rs
110 impl crate::Foo {}
111 //- /b.rs
112 impl crate::Foo {}
113 ",
114 &[
115 "impl IMPL_BLOCK FileId(2) [0; 18)",
116 "impl IMPL_BLOCK FileId(3) [0; 18)",
117 ],
118 );
119 }
120}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 43c8bea71..5d8acf9df 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -25,6 +25,7 @@ mod call_info;
25mod syntax_highlighting; 25mod syntax_highlighting;
26mod parent_module; 26mod parent_module;
27mod rename; 27mod rename;
28mod impls;
28 29
29#[cfg(test)] 30#[cfg(test)]
30mod marks; 31mod marks;
@@ -58,6 +59,13 @@ pub use ra_ide_api_light::{
58pub use ra_db::{ 59pub use ra_db::{
59 Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId 60 Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId
60}; 61};
62pub use hir::Documentation;
63
64// We use jemalloc mainly to get heap usage statistics, actual performance
65// differnece is not measures.
66#[cfg(feature = "jemalloc")]
67#[global_allocator]
68static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
61 69
62pub type Cancelable<T> = Result<T, Canceled>; 70pub type Cancelable<T> = Result<T, Canceled>;
63 71
@@ -260,7 +268,7 @@ impl<T> RangeInfo<T> {
260#[derive(Debug)] 268#[derive(Debug)]
261pub struct CallInfo { 269pub struct CallInfo {
262 pub label: String, 270 pub label: String,
263 pub doc: Option<String>, 271 pub doc: Option<Documentation>,
264 pub parameters: Vec<String>, 272 pub parameters: Vec<String>,
265 pub active_parameter: Option<usize>, 273 pub active_parameter: Option<usize>,
266} 274}
@@ -286,6 +294,10 @@ impl AnalysisHost {
286 self.db.apply_change(change) 294 self.db.apply_change(change)
287 } 295 }
288 296
297 pub fn maybe_collect_garbage(&mut self) {
298 self.db.maybe_collect_garbage();
299 }
300
289 pub fn collect_garbage(&mut self) { 301 pub fn collect_garbage(&mut self) {
290 self.db.collect_garbage(); 302 self.db.collect_garbage();
291 } 303 }
@@ -405,6 +417,13 @@ impl Analysis {
405 self.with_db(|db| goto_definition::goto_definition(db, position)) 417 self.with_db(|db| goto_definition::goto_definition(db, position))
406 } 418 }
407 419
420 pub fn goto_implementation(
421 &self,
422 position: FilePosition,
423 ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> {
424 self.with_db(|db| impls::goto_implementation(db, position))
425 }
426
408 /// Finds all usages of the reference at point. 427 /// Finds all usages of the reference at point.
409 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 428 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
410 self.with_db(|db| db.find_all_refs(position)) 429 self.with_db(|db| db.find_all_refs(position))
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 846c76cfe..0f2d22ab2 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -2,7 +2,6 @@ use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; 4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
5use ra_db::mock::FileMap;
6 5
7use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId}; 6use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId};
8 7
@@ -83,15 +82,14 @@ impl MockAnalysis {
83 } 82 }
84 pub fn analysis_host(self) -> AnalysisHost { 83 pub fn analysis_host(self) -> AnalysisHost {
85 let mut host = AnalysisHost::default(); 84 let mut host = AnalysisHost::default();
86 let mut file_map = FileMap::default();
87 let source_root = SourceRootId(0); 85 let source_root = SourceRootId(0);
88 let mut change = AnalysisChange::new(); 86 let mut change = AnalysisChange::new();
89 change.add_root(source_root, true); 87 change.add_root(source_root, true);
90 let mut crate_graph = CrateGraph::default(); 88 let mut crate_graph = CrateGraph::default();
91 for (path, contents) in self.files.into_iter() { 89 for (i, (path, contents)) in self.files.into_iter().enumerate() {
92 assert!(path.starts_with('/')); 90 assert!(path.starts_with('/'));
93 let path = RelativePathBuf::from_path(&path[1..]).unwrap(); 91 let path = RelativePathBuf::from_path(&path[1..]).unwrap();
94 let file_id = file_map.add(path.clone()); 92 let file_id = FileId(i as u32 + 1);
95 if path == "/lib.rs" || path == "/main.rs" { 93 if path == "/lib.rs" || path == "/main.rs" {
96 crate_graph.add_crate_root(file_id); 94 crate_graph.add_crate_root(file_id);
97 } 95 }
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs
index d73d4afa7..5ccb5cc2e 100644
--- a/crates/ra_ide_api/src/navigation_target.rs
+++ b/crates/ra_ide_api/src/navigation_target.rs
@@ -147,6 +147,16 @@ impl NavigationTarget {
147 } 147 }
148 } 148 }
149 149
150 pub(crate) fn from_impl_block(
151 db: &RootDatabase,
152 module: hir::Module,
153 impl_block: &hir::ImplBlock,
154 ) -> NavigationTarget {
155 let (file_id, _) = module.definition_source(db);
156 let node = module.impl_source(db, impl_block.id());
157 NavigationTarget::from_syntax(file_id, "impl".into(), None, node.syntax())
158 }
159
150 #[cfg(test)] 160 #[cfg(test)]
151 pub(crate) fn assert_match(&self, expected: &str) { 161 pub(crate) fn assert_match(&self, expected: &str) {
152 let actual = self.debug_render(); 162 let actual = self.debug_render();
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs
index e11eed223..bd355dd78 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide_api/src/status.rs
@@ -15,9 +15,13 @@ use crate::{
15 symbol_index::{SymbolIndex, LibrarySymbolsQuery}, 15 symbol_index::{SymbolIndex, LibrarySymbolsQuery},
16}; 16};
17 17
18pub(crate) fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
19 db.query(ParseQuery).entries::<SyntaxTreeStats>()
20}
21
18pub(crate) fn status(db: &RootDatabase) -> String { 22pub(crate) fn status(db: &RootDatabase) -> String {
19 let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); 23 let files_stats = db.query(FileTextQuery).entries::<FilesStats>();
20 let syntax_tree_stats = db.query(ParseQuery).entries::<SyntaxTreeStats>(); 24 let syntax_tree_stats = syntax_tree_stats(db);
21 let symbols_stats = db 25 let symbols_stats = db
22 .query(LibrarySymbolsQuery) 26 .query(LibrarySymbolsQuery)
23 .entries::<LibrarySymbolsStats>(); 27 .entries::<LibrarySymbolsStats>();
@@ -26,8 +30,13 @@ pub(crate) fn status(db: &RootDatabase) -> String {
26 interner.len() 30 interner.len()
27 }; 31 };
28 format!( 32 format!(
29 "{}\n{}\n{}\nn_defs {}\n", 33 "{}\n{}\n{}\n{} defs\n\nmemory:\n{}\ngc {:?} seconds ago",
30 files_stats, symbols_stats, syntax_tree_stats, n_defs 34 files_stats,
35 symbols_stats,
36 syntax_tree_stats,
37 n_defs,
38 MemoryStats::current(),
39 db.last_gc.elapsed().as_secs(),
31 ) 40 )
32} 41}
33 42
@@ -58,9 +67,9 @@ impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats {
58} 67}
59 68
60#[derive(Default)] 69#[derive(Default)]
61struct SyntaxTreeStats { 70pub(crate) struct SyntaxTreeStats {
62 total: usize, 71 total: usize,
63 retained: usize, 72 pub(crate) retained: usize,
64 retained_size: Bytes, 73 retained_size: Bytes,
65} 74}
66 75
@@ -118,6 +127,40 @@ impl FromIterator<TableEntry<SourceRootId, Arc<SymbolIndex>>> for LibrarySymbols
118 } 127 }
119} 128}
120 129
130struct MemoryStats {
131 allocated: Bytes,
132 resident: Bytes,
133}
134
135impl MemoryStats {
136 #[cfg(feature = "jemalloc")]
137 fn current() -> MemoryStats {
138 jemalloc_ctl::epoch().unwrap();
139 MemoryStats {
140 allocated: Bytes(jemalloc_ctl::stats::allocated().unwrap()),
141 resident: Bytes(jemalloc_ctl::stats::resident().unwrap()),
142 }
143 }
144
145 #[cfg(not(feature = "jemalloc"))]
146 fn current() -> MemoryStats {
147 MemoryStats {
148 allocated: Bytes(0),
149 resident: Bytes(0),
150 }
151 }
152}
153
154impl fmt::Display for MemoryStats {
155 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
156 write!(
157 fmt,
158 "{} allocated {} resident",
159 self.allocated, self.resident,
160 )
161 }
162}
163
121#[derive(Default)] 164#[derive(Default)]
122struct Bytes(usize); 165struct Bytes(usize);
123 166
diff --git a/crates/ra_ide_api/tests/test/main.rs b/crates/ra_ide_api/tests/test/main.rs
index 756075190..c2cb38f7e 100644
--- a/crates/ra_ide_api/tests/test/main.rs
+++ b/crates/ra_ide_api/tests/test/main.rs
@@ -1,9 +1,9 @@
1use insta::assert_debug_snapshot_matches;
1use ra_ide_api::{ 2use ra_ide_api::{
2 AnalysisChange, 3 mock_analysis::{single_file, single_file_with_position, MockAnalysis},
3 CrateGraph, FileId, mock_analysis::{MockAnalysis, single_file, single_file_with_position}, Query, 4 AnalysisChange, CrateGraph, FileId, Query,
4}; 5};
5use ra_syntax::TextRange; 6use ra_syntax::TextRange;
6use insta::assert_debug_snapshot_matches;
7 7
8#[test] 8#[test]
9fn test_unresolved_module_diagnostic() { 9fn test_unresolved_module_diagnostic() {
@@ -26,12 +26,12 @@ fn test_resolve_crate_root() {
26 " 26 "
27 //- /bar.rs 27 //- /bar.rs
28 mod foo; 28 mod foo;
29 //- /bar/foo.rs 29 //- /foo.rs
30 // emtpy <|> 30 // empty <|>
31 ", 31 ",
32 ); 32 );
33 let root_file = mock.id_of("/bar.rs"); 33 let root_file = mock.id_of("/bar.rs");
34 let mod_file = mock.id_of("/bar/foo.rs"); 34 let mod_file = mock.id_of("/foo.rs");
35 let mut host = mock.analysis_host(); 35 let mut host = mock.analysis_host();
36 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); 36 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
37 37
diff --git a/crates/ra_ide_api_light/src/assists.rs b/crates/ra_ide_api_light/src/assists.rs
index aea8397c9..8905b0419 100644
--- a/crates/ra_ide_api_light/src/assists.rs
+++ b/crates/ra_ide_api_light/src/assists.rs
@@ -197,6 +197,14 @@ fn check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &s
197} 197}
198 198
199#[cfg(test)] 199#[cfg(test)]
200fn check_assist_not_applicable(assist: fn(AssistCtx) -> Option<Assist>, text: &str) {
201 crate::test_utils::check_action_not_applicable(text, |file, off| {
202 let range = TextRange::offset_len(off, 0.into());
203 AssistCtx::new(file, range).apply(assist)
204 })
205}
206
207#[cfg(test)]
200fn check_assist_range(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) { 208fn check_assist_range(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) {
201 crate::test_utils::check_action_range(before, after, |file, range| { 209 crate::test_utils::check_action_range(before, after, |file, range| {
202 AssistCtx::new(file, range).apply(assist) 210 AssistCtx::new(file, range).apply(assist)
diff --git a/crates/ra_ide_api_light/src/assists/introduce_variable.rs b/crates/ra_ide_api_light/src/assists/introduce_variable.rs
index 3e4434c23..ed13bddc4 100644
--- a/crates/ra_ide_api_light/src/assists/introduce_variable.rs
+++ b/crates/ra_ide_api_light/src/assists/introduce_variable.rs
@@ -1,16 +1,19 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode}, 2 ast::{self, AstNode},
3 SyntaxKind::WHITESPACE, 3 SyntaxKind::{
4 SyntaxNode, TextUnit, 4 WHITESPACE, MATCH_ARM, LAMBDA_EXPR, PATH_EXPR, BREAK_EXPR, LOOP_EXPR, RETURN_EXPR, COMMENT
5 }, SyntaxNode, TextUnit,
5}; 6};
6 7
7use crate::assists::{AssistCtx, Assist}; 8use crate::assists::{AssistCtx, Assist};
8 9
9pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> { 10pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> {
10 let node = ctx.covering_node(); 11 let node = ctx.covering_node();
11 let expr = node.ancestors().filter_map(ast::Expr::cast).next()?; 12 if !valid_covering_node(node) {
12 13 return None;
13 let anchor_stmt = anchor_stmt(expr)?; 14 }
15 let expr = node.ancestors().filter_map(valid_target_expr).next()?;
16 let (anchor_stmt, wrap_in_block) = anchor_stmt(expr)?;
14 let indent = anchor_stmt.prev_sibling()?; 17 let indent = anchor_stmt.prev_sibling()?;
15 if indent.kind() != WHITESPACE { 18 if indent.kind() != WHITESPACE {
16 return None; 19 return None;
@@ -18,7 +21,14 @@ pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> {
18 ctx.build("introduce variable", move |edit| { 21 ctx.build("introduce variable", move |edit| {
19 let mut buf = String::new(); 22 let mut buf = String::new();
20 23
21 buf.push_str("let var_name = "); 24 let cursor_offset = if wrap_in_block {
25 buf.push_str("{ let var_name = ");
26 TextUnit::of_str("{ let ")
27 } else {
28 buf.push_str("let var_name = ");
29 TextUnit::of_str("let ")
30 };
31
22 expr.syntax().text().push_to(&mut buf); 32 expr.syntax().text().push_to(&mut buf);
23 let full_stmt = ast::ExprStmt::cast(anchor_stmt); 33 let full_stmt = ast::ExprStmt::cast(anchor_stmt);
24 let is_full_stmt = if let Some(expr_stmt) = full_stmt { 34 let is_full_stmt = if let Some(expr_stmt) = full_stmt {
@@ -36,35 +46,64 @@ pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> {
36 indent.text().push_to(&mut buf); 46 indent.text().push_to(&mut buf);
37 edit.replace(expr.syntax().range(), "var_name".to_string()); 47 edit.replace(expr.syntax().range(), "var_name".to_string());
38 edit.insert(anchor_stmt.range().start(), buf); 48 edit.insert(anchor_stmt.range().start(), buf);
49 if wrap_in_block {
50 edit.insert(anchor_stmt.range().end(), " }");
51 }
39 } 52 }
40 edit.set_cursor(anchor_stmt.range().start() + TextUnit::of_str("let ")); 53 edit.set_cursor(anchor_stmt.range().start() + cursor_offset);
41 }) 54 })
42} 55}
43 56
44/// Statement or last in the block expression, which will follow 57fn valid_covering_node(node: &SyntaxNode) -> bool {
45/// the freshly introduced var. 58 node.kind() != COMMENT
46fn anchor_stmt(expr: &ast::Expr) -> Option<&SyntaxNode> { 59}
47 expr.syntax().ancestors().find(|&node| { 60/// Check wether the node is a valid expression which can be extracted to a variable.
61/// In general that's true for any expression, but in some cases that would produce invalid code.
62fn valid_target_expr(node: &SyntaxNode) -> Option<&ast::Expr> {
63 return match node.kind() {
64 PATH_EXPR => None,
65 BREAK_EXPR => ast::BreakExpr::cast(node).and_then(|e| e.expr()),
66 RETURN_EXPR => ast::ReturnExpr::cast(node).and_then(|e| e.expr()),
67 LOOP_EXPR => ast::ReturnExpr::cast(node).and_then(|e| e.expr()),
68 _ => ast::Expr::cast(node),
69 };
70}
71
72/// Returns the syntax node which will follow the freshly introduced var
73/// and a boolean indicating whether we have to wrap it within a { } block
74/// to produce correct code.
75/// It can be a statement, the last in a block expression or a wanna be block
76/// expression like a lamba or match arm.
77fn anchor_stmt(expr: &ast::Expr) -> Option<(&SyntaxNode, bool)> {
78 expr.syntax().ancestors().find_map(|node| {
48 if ast::Stmt::cast(node).is_some() { 79 if ast::Stmt::cast(node).is_some() {
49 return true; 80 return Some((node, false));
50 } 81 }
82
51 if let Some(expr) = node 83 if let Some(expr) = node
52 .parent() 84 .parent()
53 .and_then(ast::Block::cast) 85 .and_then(ast::Block::cast)
54 .and_then(|it| it.expr()) 86 .and_then(|it| it.expr())
55 { 87 {
56 if expr.syntax() == node { 88 if expr.syntax() == node {
57 return true; 89 return Some((node, false));
90 }
91 }
92
93 if let Some(parent) = node.parent() {
94 if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR {
95 return Some((node, true));
58 } 96 }
59 } 97 }
60 false 98
99 None
61 }) 100 })
62} 101}
63 102
64#[cfg(test)] 103#[cfg(test)]
65mod tests { 104mod tests {
66 use super::*; 105 use super::*;
67 use crate::assists::check_assist_range; 106 use crate::assists::{ check_assist, check_assist_not_applicable, check_assist_range };
68 107
69 #[test] 108 #[test]
70 fn test_introduce_var_simple() { 109 fn test_introduce_var_simple() {
@@ -161,4 +200,232 @@ fn foo() {
161}", 200}",
162 ); 201 );
163 } 202 }
203
204 #[test]
205 fn test_introduce_var_in_match_arm_no_block() {
206 check_assist_range(
207 introduce_variable,
208 "
209fn main() {
210 let x = true;
211 let tuple = match x {
212 true => (<|>2 + 2<|>, true)
213 _ => (0, false)
214 };
215}
216",
217 "
218fn main() {
219 let x = true;
220 let tuple = match x {
221 true => { let <|>var_name = 2 + 2; (var_name, true) }
222 _ => (0, false)
223 };
224}
225",
226 );
227 }
228
229 #[test]
230 fn test_introduce_var_in_match_arm_with_block() {
231 check_assist_range(
232 introduce_variable,
233 "
234fn main() {
235 let x = true;
236 let tuple = match x {
237 true => {
238 let y = 1;
239 (<|>2 + y<|>, true)
240 }
241 _ => (0, false)
242 };
243}
244",
245 "
246fn main() {
247 let x = true;
248 let tuple = match x {
249 true => {
250 let y = 1;
251 let <|>var_name = 2 + y;
252 (var_name, true)
253 }
254 _ => (0, false)
255 };
256}
257",
258 );
259 }
260
261 #[test]
262 fn test_introduce_var_in_closure_no_block() {
263 check_assist_range(
264 introduce_variable,
265 "
266fn main() {
267 let lambda = |x: u32| <|>x * 2<|>;
268}
269",
270 "
271fn main() {
272 let lambda = |x: u32| { let <|>var_name = x * 2; var_name };
273}
274",
275 );
276 }
277
278 #[test]
279 fn test_introduce_var_in_closure_with_block() {
280 check_assist_range(
281 introduce_variable,
282 "
283fn main() {
284 let lambda = |x: u32| { <|>x * 2<|> };
285}
286",
287 "
288fn main() {
289 let lambda = |x: u32| { let <|>var_name = x * 2; var_name };
290}
291",
292 );
293 }
294
295 #[test]
296 fn test_introduce_var_path_simple() {
297 check_assist(
298 introduce_variable,
299 "
300fn main() {
301 let o = S<|>ome(true);
302}
303",
304 "
305fn main() {
306 let <|>var_name = Some(true);
307 let o = var_name;
308}
309",
310 );
311 }
312
313 #[test]
314 fn test_introduce_var_path_method() {
315 check_assist(
316 introduce_variable,
317 "
318fn main() {
319 let v = b<|>ar.foo();
320}
321",
322 "
323fn main() {
324 let <|>var_name = bar.foo();
325 let v = var_name;
326}
327",
328 );
329 }
330
331 #[test]
332 fn test_introduce_var_return() {
333 check_assist(
334 introduce_variable,
335 "
336fn foo() -> u32 {
337 r<|>eturn 2 + 2;
338}
339",
340 "
341fn foo() -> u32 {
342 let <|>var_name = 2 + 2;
343 return var_name;
344}
345",
346 );
347 }
348
349 #[test]
350 fn test_introduce_var_break() {
351 check_assist(
352 introduce_variable,
353 "
354fn main() {
355 let result = loop {
356 b<|>reak 2 + 2;
357 };
358}
359",
360 "
361fn main() {
362 let result = loop {
363 let <|>var_name = 2 + 2;
364 break var_name;
365 };
366}
367",
368 );
369 }
370
371 #[test]
372 fn test_introduce_var_for_cast() {
373 check_assist(
374 introduce_variable,
375 "
376fn main() {
377 let v = 0f32 a<|>s u32;
378}
379",
380 "
381fn main() {
382 let <|>var_name = 0f32 as u32;
383 let v = var_name;
384}
385",
386 );
387 }
388
389 #[test]
390 fn test_introduce_var_for_return_not_applicable() {
391 check_assist_not_applicable(
392 introduce_variable,
393 "
394fn foo() {
395 r<|>eturn;
396}
397",
398 );
399 }
400
401 #[test]
402 fn test_introduce_var_for_break_not_applicable() {
403 check_assist_not_applicable(
404 introduce_variable,
405 "
406fn main() {
407 loop {
408 b<|>reak;
409 };
410}
411",
412 );
413 }
414
415 #[test]
416 fn test_introduce_var_in_comment_not_applicable() {
417 check_assist_not_applicable(
418 introduce_variable,
419 "
420fn main() {
421 let x = true;
422 let tuple = match x {
423 // c<|>omment
424 true => (2 + 2, true)
425 _ => (0, false)
426 };
427}
428",
429 );
430 }
164} 431}
diff --git a/crates/ra_ide_api_light/src/test_utils.rs b/crates/ra_ide_api_light/src/test_utils.rs
index dc2470aa3..22ded2435 100644
--- a/crates/ra_ide_api_light/src/test_utils.rs
+++ b/crates/ra_ide_api_light/src/test_utils.rs
@@ -23,6 +23,18 @@ pub fn check_action<F: Fn(&SourceFile, TextUnit) -> Option<LocalEdit>>(
23 assert_eq_text!(after, &actual); 23 assert_eq_text!(after, &actual);
24} 24}
25 25
26pub fn check_action_not_applicable<F: Fn(&SourceFile, TextUnit) -> Option<LocalEdit>>(
27 text: &str,
28 f: F,
29) {
30 let (text_cursor_pos, text) = extract_offset(text);
31 let file = SourceFile::parse(&text);
32 assert!(
33 f(&file, text_cursor_pos).is_none(),
34 "code action is applicable but it shouldn't"
35 );
36}
37
26pub fn check_action_range<F: Fn(&SourceFile, TextRange) -> Option<LocalEdit>>( 38pub fn check_action_range<F: Fn(&SourceFile, TextRange) -> Option<LocalEdit>>(
27 before: &str, 39 before: &str,
28 after: &str, 40 after: &str,
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 160d2f672..bb92747f2 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -34,3 +34,6 @@ ra_vfs = { path = "../ra_vfs" }
34[dev-dependencies] 34[dev-dependencies]
35tempfile = "3" 35tempfile = "3"
36test_utils = { path = "../test_utils" } 36test_utils = { path = "../test_utils" }
37
38[features]
39jemalloc = [ "ra_ide_api/jemalloc" ]
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index bca079d65..254624487 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -2,7 +2,7 @@ use lsp_types::{
2 CodeActionProviderCapability, CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions, 2 CodeActionProviderCapability, CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions,
3 ExecuteCommandOptions, FoldingRangeProviderCapability, RenameOptions, RenameProviderCapability, 3 ExecuteCommandOptions, FoldingRangeProviderCapability, RenameOptions, RenameProviderCapability,
4 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, 4 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
5 TextDocumentSyncOptions, 5 TextDocumentSyncOptions, ImplementationProviderCapability,
6}; 6};
7 7
8pub fn server_capabilities() -> ServerCapabilities { 8pub fn server_capabilities() -> ServerCapabilities {
@@ -26,7 +26,7 @@ pub fn server_capabilities() -> ServerCapabilities {
26 }), 26 }),
27 definition_provider: Some(true), 27 definition_provider: Some(true),
28 type_definition_provider: None, 28 type_definition_provider: None,
29 implementation_provider: None, 29 implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
30 references_provider: Some(true), 30 references_provider: Some(true),
31 document_highlight_provider: Some(true), 31 document_highlight_provider: Some(true),
32 document_symbol_provider: Some(true), 32 document_symbol_provider: Some(true),
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 8c87f5195..c033ecdea 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -87,13 +87,6 @@ impl ConvWith for CompletionItem {
87 None 87 None
88 }; 88 };
89 89
90 let documentation = self.documentation().map(|value| {
91 Documentation::MarkupContent(MarkupContent {
92 kind: MarkupKind::Markdown,
93 value: value.to_string(),
94 })
95 });
96
97 let mut res = lsp_types::CompletionItem { 90 let mut res = lsp_types::CompletionItem {
98 label: self.label().to_string(), 91 label: self.label().to_string(),
99 detail: self.detail().map(|it| it.to_string()), 92 detail: self.detail().map(|it| it.to_string()),
@@ -101,7 +94,7 @@ impl ConvWith for CompletionItem {
101 kind: self.kind().map(|it| it.conv()), 94 kind: self.kind().map(|it| it.conv()),
102 text_edit: Some(text_edit), 95 text_edit: Some(text_edit),
103 additional_text_edits, 96 additional_text_edits,
104 documentation: documentation, 97 documentation: self.documentation().map(|it| it.conv()),
105 ..Default::default() 98 ..Default::default()
106 }; 99 };
107 res.insert_text_format = Some(match self.insert_text_format() { 100 res.insert_text_format = Some(match self.insert_text_format() {
@@ -160,6 +153,16 @@ impl ConvWith for Range {
160 } 153 }
161} 154}
162 155
156impl Conv for ra_ide_api::Documentation {
157 type Output = lsp_types::Documentation;
158 fn conv(self) -> Documentation {
159 Documentation::MarkupContent(MarkupContent {
160 kind: MarkupKind::Markdown,
161 value: crate::markdown::sanitize_markdown(self).into(),
162 })
163 }
164}
165
163impl ConvWith for TextEdit { 166impl ConvWith for TextEdit {
164 type Ctx = LineIndex; 167 type Ctx = LineIndex;
165 type Output = Vec<lsp_types::TextEdit>; 168 type Output = Vec<lsp_types::TextEdit>;
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index f93d4b37d..5b5f3b948 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -2,6 +2,7 @@ mod caps;
2mod cargo_target_spec; 2mod cargo_target_spec;
3mod conv; 3mod conv;
4mod main_loop; 4mod main_loop;
5mod markdown;
5mod project_model; 6mod project_model;
6pub mod req; 7pub mod req;
7mod server_world; 8mod server_world;
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index ddd20a41f..df390c19e 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -172,6 +172,7 @@ fn main_loop_inner(
172 172
173 let (libdata_sender, libdata_receiver) = unbounded(); 173 let (libdata_sender, libdata_receiver) = unbounded();
174 loop { 174 loop {
175 state.maybe_collect_garbage();
175 log::trace!("selecting"); 176 log::trace!("selecting");
176 let event = select! { 177 let event = select! {
177 recv(msg_receiver) -> msg => match msg { 178 recv(msg_receiver) -> msg => match msg {
@@ -207,7 +208,7 @@ fn main_loop_inner(
207 }; 208 };
208 match req.cast::<req::CollectGarbage>() { 209 match req.cast::<req::CollectGarbage>() {
209 Ok((id, ())) => { 210 Ok((id, ())) => {
210 state.collect_garbadge(); 211 state.collect_garbage();
211 let resp = RawResponse::ok::<req::CollectGarbage>(id, &()); 212 let resp = RawResponse::ok::<req::CollectGarbage>(id, &());
212 msg_sender.send(RawMessage::Response(resp)).unwrap() 213 msg_sender.send(RawMessage::Response(resp)).unwrap()
213 } 214 }
@@ -304,6 +305,7 @@ fn on_request(
304 .on::<req::DocumentSymbolRequest>(handlers::handle_document_symbol)? 305 .on::<req::DocumentSymbolRequest>(handlers::handle_document_symbol)?
305 .on::<req::WorkspaceSymbol>(handlers::handle_workspace_symbol)? 306 .on::<req::WorkspaceSymbol>(handlers::handle_workspace_symbol)?
306 .on::<req::GotoDefinition>(handlers::handle_goto_definition)? 307 .on::<req::GotoDefinition>(handlers::handle_goto_definition)?
308 .on::<req::GotoImplementation>(handlers::handle_goto_implementation)?
307 .on::<req::ParentModule>(handlers::handle_parent_module)? 309 .on::<req::ParentModule>(handlers::handle_parent_module)?
308 .on::<req::Runnables>(handlers::handle_runnables)? 310 .on::<req::Runnables>(handlers::handle_runnables)?
309 .on::<req::DecorationsRequest>(handlers::handle_decorations)? 311 .on::<req::DecorationsRequest>(handlers::handle_decorations)?
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index ace3da020..74554f15c 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -1,7 +1,7 @@
1use gen_lsp_server::ErrorCode; 1use gen_lsp_server::ErrorCode;
2use lsp_types::{ 2use lsp_types::{
3 CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, 3 CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity,
4 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, 4 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
5 FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, 5 FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
6 MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, 6 MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range,
7 RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, 7 RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit,
@@ -229,6 +229,26 @@ pub fn handle_goto_definition(
229 Ok(Some(req::GotoDefinitionResponse::Link(res))) 229 Ok(Some(req::GotoDefinitionResponse::Link(res)))
230} 230}
231 231
232pub fn handle_goto_implementation(
233 world: ServerWorld,
234 params: req::TextDocumentPositionParams,
235) -> Result<Option<req::GotoImplementationResponse>> {
236 let position = params.try_conv_with(&world)?;
237 let line_index = world.analysis().file_line_index(position.file_id);
238 let nav_info = match world.analysis().goto_implementation(position)? {
239 None => return Ok(None),
240 Some(it) => it,
241 };
242 let nav_range = nav_info.range;
243 let res = nav_info
244 .info
245 .into_iter()
246 .map(|nav| RangeInfo::new(nav_range, nav))
247 .map(|nav| to_location_link(&nav, &world, &line_index))
248 .collect::<Result<Vec<_>>>()?;
249 Ok(Some(req::GotoDefinitionResponse::Link(res)))
250}
251
232pub fn handle_parent_module( 252pub fn handle_parent_module(
233 world: ServerWorld, 253 world: ServerWorld,
234 params: req::TextDocumentPositionParams, 254 params: req::TextDocumentPositionParams,
@@ -401,12 +421,9 @@ pub fn handle_signature_help(
401 documentation: None, 421 documentation: None,
402 }) 422 })
403 .collect(); 423 .collect();
404 let documentation = call_info.doc.map(|value| { 424
405 Documentation::MarkupContent(MarkupContent { 425 let documentation = call_info.doc.map(|it| it.conv());
406 kind: MarkupKind::Markdown, 426
407 value,
408 })
409 });
410 let sig_info = SignatureInformation { 427 let sig_info = SignatureInformation {
411 label: call_info.label, 428 label: call_info.label,
412 documentation, 429 documentation,
@@ -581,7 +598,7 @@ pub fn handle_code_action(
581 let edit = source_edit.try_conv_with(&world)?; 598 let edit = source_edit.try_conv_with(&world)?;
582 let cmd = Command { 599 let cmd = Command {
583 title, 600 title,
584 command: "ra-lsp.applySourceChange".to_string(), 601 command: "rust-analyzer.applySourceChange".to_string(),
585 arguments: Some(vec![to_value(edit).unwrap()]), 602 arguments: Some(vec![to_value(edit).unwrap()]),
586 }; 603 };
587 res.push(cmd); 604 res.push(cmd);
@@ -623,7 +640,7 @@ pub fn handle_code_lens(
623 range, 640 range,
624 command: Some(Command { 641 command: Some(Command {
625 title: title.into(), 642 title: title.into(),
626 command: "ra-lsp.run-single".into(), 643 command: "rust-analyzer.runSingle".into(),
627 arguments: Some(vec![to_value(r).unwrap()]), 644 arguments: Some(vec![to_value(r).unwrap()]),
628 }), 645 }),
629 data: None, 646 data: None,
diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs
new file mode 100644
index 000000000..f505755e8
--- /dev/null
+++ b/crates/ra_lsp_server/src/markdown.rs
@@ -0,0 +1,38 @@
1use ra_ide_api::Documentation;
2
3pub(crate) fn sanitize_markdown(docs: Documentation) -> Documentation {
4 let docs: String = docs.into();
5
6 // Massage markdown
7 let mut processed_lines = Vec::new();
8 let mut in_code_block = false;
9 for line in docs.lines() {
10 if line.starts_with("```") {
11 in_code_block = !in_code_block;
12 }
13
14 let line = if in_code_block && line.starts_with("```") && !line.contains("rust") {
15 "```rust".into()
16 } else {
17 line.to_string()
18 };
19
20 processed_lines.push(line);
21 }
22
23 Documentation::new(&processed_lines.join("\n"))
24}
25
26#[cfg(test)]
27mod tests {
28 use super::*;
29
30 #[test]
31 fn test_codeblock_adds_rust() {
32 let comment = "```\nfn some_rust() {}\n```";
33 assert_eq!(
34 sanitize_markdown(Documentation::new(comment)).contents(),
35 "```rust\nfn some_rust() {}\n```"
36 );
37 }
38}
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 5968e592b..e224ede80 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -8,7 +8,7 @@ pub use lsp_types::{
8 CompletionParams, CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams, 8 CompletionParams, CompletionResponse, DocumentOnTypeFormattingParams, DocumentSymbolParams,
9 DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult, 9 DocumentSymbolResponse, ExecuteCommandParams, Hover, InitializeResult,
10 PublishDiagnosticsParams, ReferenceParams, SignatureHelp, TextDocumentEdit, 10 PublishDiagnosticsParams, ReferenceParams, SignatureHelp, TextDocumentEdit,
11 TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, 11 TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams
12}; 12};
13 13
14pub enum AnalyzerStatus {} 14pub enum AnalyzerStatus {}
@@ -16,7 +16,7 @@ pub enum AnalyzerStatus {}
16impl Request for AnalyzerStatus { 16impl Request for AnalyzerStatus {
17 type Params = (); 17 type Params = ();
18 type Result = String; 18 type Result = String;
19 const METHOD: &'static str = "ra/analyzerStatus"; 19 const METHOD: &'static str = "rust-analyzer/analyzerStatus";
20} 20}
21 21
22pub enum CollectGarbage {} 22pub enum CollectGarbage {}
@@ -24,7 +24,7 @@ pub enum CollectGarbage {}
24impl Request for CollectGarbage { 24impl Request for CollectGarbage {
25 type Params = (); 25 type Params = ();
26 type Result = (); 26 type Result = ();
27 const METHOD: &'static str = "ra/collectGarbage"; 27 const METHOD: &'static str = "rust-analyzer/collectGarbage";
28} 28}
29 29
30pub enum SyntaxTree {} 30pub enum SyntaxTree {}
@@ -32,7 +32,7 @@ pub enum SyntaxTree {}
32impl Request for SyntaxTree { 32impl Request for SyntaxTree {
33 type Params = SyntaxTreeParams; 33 type Params = SyntaxTreeParams;
34 type Result = String; 34 type Result = String;
35 const METHOD: &'static str = "m/syntaxTree"; 35 const METHOD: &'static str = "rust-analyzer/syntaxTree";
36} 36}
37 37
38#[derive(Deserialize, Debug)] 38#[derive(Deserialize, Debug)]
@@ -46,7 +46,7 @@ pub enum ExtendSelection {}
46impl Request for ExtendSelection { 46impl Request for ExtendSelection {
47 type Params = ExtendSelectionParams; 47 type Params = ExtendSelectionParams;
48 type Result = ExtendSelectionResult; 48 type Result = ExtendSelectionResult;
49 const METHOD: &'static str = "m/extendSelection"; 49 const METHOD: &'static str = "rust-analyzer/extendSelection";
50} 50}
51 51
52#[derive(Deserialize, Debug)] 52#[derive(Deserialize, Debug)]
@@ -67,7 +67,7 @@ pub enum FindMatchingBrace {}
67impl Request for FindMatchingBrace { 67impl Request for FindMatchingBrace {
68 type Params = FindMatchingBraceParams; 68 type Params = FindMatchingBraceParams;
69 type Result = Vec<Position>; 69 type Result = Vec<Position>;
70 const METHOD: &'static str = "m/findMatchingBrace"; 70 const METHOD: &'static str = "rust-analyzer/findMatchingBrace";
71} 71}
72 72
73#[derive(Deserialize, Debug)] 73#[derive(Deserialize, Debug)]
@@ -82,14 +82,14 @@ pub enum DecorationsRequest {}
82impl Request for DecorationsRequest { 82impl Request for DecorationsRequest {
83 type Params = TextDocumentIdentifier; 83 type Params = TextDocumentIdentifier;
84 type Result = Vec<Decoration>; 84 type Result = Vec<Decoration>;
85 const METHOD: &'static str = "m/decorationsRequest"; 85 const METHOD: &'static str = "rust-analyzer/decorationsRequest";
86} 86}
87 87
88pub enum PublishDecorations {} 88pub enum PublishDecorations {}
89 89
90impl Notification for PublishDecorations { 90impl Notification for PublishDecorations {
91 type Params = PublishDecorationsParams; 91 type Params = PublishDecorationsParams;
92 const METHOD: &'static str = "m/publishDecorations"; 92 const METHOD: &'static str = "rust-analyzer/publishDecorations";
93} 93}
94 94
95#[derive(Serialize, Debug)] 95#[derive(Serialize, Debug)]
@@ -112,7 +112,7 @@ pub enum ParentModule {}
112impl Request for ParentModule { 112impl Request for ParentModule {
113 type Params = TextDocumentPositionParams; 113 type Params = TextDocumentPositionParams;
114 type Result = Vec<Location>; 114 type Result = Vec<Location>;
115 const METHOD: &'static str = "m/parentModule"; 115 const METHOD: &'static str = "rust-analyzer/parentModule";
116} 116}
117 117
118pub enum JoinLines {} 118pub enum JoinLines {}
@@ -120,7 +120,7 @@ pub enum JoinLines {}
120impl Request for JoinLines { 120impl Request for JoinLines {
121 type Params = JoinLinesParams; 121 type Params = JoinLinesParams;
122 type Result = SourceChange; 122 type Result = SourceChange;
123 const METHOD: &'static str = "m/joinLines"; 123 const METHOD: &'static str = "rust-analyzer/joinLines";
124} 124}
125 125
126#[derive(Deserialize, Debug)] 126#[derive(Deserialize, Debug)]
@@ -135,7 +135,7 @@ pub enum OnEnter {}
135impl Request for OnEnter { 135impl Request for OnEnter {
136 type Params = TextDocumentPositionParams; 136 type Params = TextDocumentPositionParams;
137 type Result = Option<SourceChange>; 137 type Result = Option<SourceChange>;
138 const METHOD: &'static str = "m/onEnter"; 138 const METHOD: &'static str = "rust-analyzer/onEnter";
139} 139}
140 140
141pub enum Runnables {} 141pub enum Runnables {}
@@ -143,7 +143,7 @@ pub enum Runnables {}
143impl Request for Runnables { 143impl Request for Runnables {
144 type Params = RunnablesParams; 144 type Params = RunnablesParams;
145 type Result = Vec<Runnable>; 145 type Result = Vec<Runnable>;
146 const METHOD: &'static str = "m/runnables"; 146 const METHOD: &'static str = "rust-analyzer/runnables";
147} 147}
148 148
149#[derive(Serialize, Deserialize, Debug)] 149#[derive(Serialize, Deserialize, Debug)]
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index bf04f1125..c2167c5d8 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -232,7 +232,11 @@ impl ServerWorldState {
232 } 232 }
233 } 233 }
234 234
235 pub fn collect_garbadge(&mut self) { 235 pub fn maybe_collect_garbage(&mut self) {
236 self.analysis_host.maybe_collect_garbage()
237 }
238
239 pub fn collect_garbage(&mut self) {
236 self.analysis_host.collect_garbage() 240 self.analysis_host.collect_garbage()
237 } 241 }
238} 242}
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs
index 8b5c43a09..bfb0645a8 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/main.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs
@@ -246,7 +246,7 @@ fn main() {}
246 "label": "create module" 246 "label": "create module"
247 } 247 }
248 ], 248 ],
249 "command": "ra-lsp.applySourceChange", 249 "command": "rust-analyzer.applySourceChange",
250 "title": "create module" 250 "title": "create module"
251 } 251 }
252 ]), 252 ]),
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index 45747e21d..99b0983b0 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -17,14 +17,14 @@ pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset<
17} 17}
18 18
19/// Finds a node of specific Ast type at offset. Note that this is slightly 19/// Finds a node of specific Ast type at offset. Note that this is slightly
20/// impercise: if the cursor is strictly betwen two nodes of the desired type, 20/// imprecise: if the cursor is strictly between two nodes of the desired type,
21/// as in 21/// as in
22/// 22///
23/// ```no-run 23/// ```no-run
24/// struct Foo {}|struct Bar; 24/// struct Foo {}|struct Bar;
25/// ``` 25/// ```
26/// 26///
27/// then the left node will be silently prefered. 27/// then the left node will be silently preferred.
28pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> { 28pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> {
29 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast)) 29 find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast))
30} 30}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index ce559882b..d0561c495 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1982,7 +1982,11 @@ impl ToOwned for MatchGuard {
1982} 1982}
1983 1983
1984 1984
1985impl MatchGuard {} 1985impl MatchGuard {
1986 pub fn expr(&self) -> Option<&Expr> {
1987 super::child_opt(self)
1988 }
1989}
1986 1990
1987// MethodCallExpr 1991// MethodCallExpr
1988#[derive(Debug, PartialEq, Eq, Hash)] 1992#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index f4841241f..d4c863705 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -418,7 +418,7 @@ Grammar(
418 ], 418 ],
419 collections: [ [ "pats", "Pat" ] ] 419 collections: [ [ "pats", "Pat" ] ]
420 ), 420 ),
421 "MatchGuard": (), 421 "MatchGuard": (options: ["Expr"]),
422 "StructLit": (options: ["Path", "NamedFieldList", ["spread", "Expr"]]), 422 "StructLit": (options: ["Path", "NamedFieldList", ["spread", "Expr"]]),
423 "NamedFieldList": (collections: [ ["fields", "NamedField"] ]), 423 "NamedFieldList": (collections: [ ["fields", "NamedField"] ]),
424 "NamedField": (options: ["NameRef", "Expr"]), 424 "NamedField": (options: ["NameRef", "Expr"]),
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 6d6d89f70..600774afd 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -360,8 +360,8 @@ fn match_arm(p: &mut Parser) -> BlockLike {
360 while p.eat(PIPE) { 360 while p.eat(PIPE) {
361 patterns::pattern(p); 361 patterns::pattern(p);
362 } 362 }
363 if p.eat(IF_KW) { 363 if p.at(IF_KW) {
364 expr(p); 364 match_guard(p);
365 } 365 }
366 p.expect(FAT_ARROW); 366 p.expect(FAT_ARROW);
367 let ret = expr_stmt(p); 367 let ret = expr_stmt(p);
@@ -369,6 +369,20 @@ fn match_arm(p: &mut Parser) -> BlockLike {
369 ret 369 ret
370} 370}
371 371
372// test match_guard
373// fn foo() {
374// match () {
375// _ if foo => (),
376// }
377// }
378fn match_guard(p: &mut Parser) -> CompletedMarker {
379 assert!(p.at(IF_KW));
380 let m = p.start();
381 p.bump();
382 expr(p);
383 m.complete(p, MATCH_GUARD)
384}
385
372// test block_expr 386// test block_expr
373// fn foo() { 387// fn foo() {
374// {}; 388// {};
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt
index 98e7535a3..b44e61879 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt
@@ -37,32 +37,33 @@ SOURCE_FILE@[0; 167)
37 PLACEHOLDER_PAT@[51; 52) 37 PLACEHOLDER_PAT@[51; 52)
38 UNDERSCORE@[51; 52) 38 UNDERSCORE@[51; 52)
39 WHITESPACE@[52; 53) 39 WHITESPACE@[52; 53)
40 IF_KW@[53; 55) 40 MATCH_GUARD@[53; 77)
41 WHITESPACE@[55; 56) 41 IF_KW@[53; 55)
42 BIN_EXPR@[56; 77) 42 WHITESPACE@[55; 56)
43 PATH_EXPR@[56; 60) 43 BIN_EXPR@[56; 77)
44 PATH@[56; 60) 44 PATH_EXPR@[56; 60)
45 PATH_SEGMENT@[56; 60) 45 PATH@[56; 60)
46 NAME_REF@[56; 60) 46 PATH_SEGMENT@[56; 60)
47 IDENT@[56; 60) "Test" 47 NAME_REF@[56; 60)
48 WHITESPACE@[60; 61) 48 IDENT@[56; 60) "Test"
49 R_ANGLE@[61; 62) 49 WHITESPACE@[60; 61)
50 WHITESPACE@[62; 63) 50 R_ANGLE@[61; 62)
51 STRUCT_LIT@[63; 77) 51 WHITESPACE@[62; 63)
52 PATH@[63; 67) 52 STRUCT_LIT@[63; 77)
53 PATH_SEGMENT@[63; 67) 53 PATH@[63; 67)
54 NAME_REF@[63; 67) 54 PATH_SEGMENT@[63; 67)
55 IDENT@[63; 67) "Test" 55 NAME_REF@[63; 67)
56 NAMED_FIELD_LIST@[67; 77) 56 IDENT@[63; 67) "Test"
57 L_CURLY@[67; 68) 57 NAMED_FIELD_LIST@[67; 77)
58 NAMED_FIELD@[68; 76) 58 L_CURLY@[67; 68)
59 NAME_REF@[68; 73) 59 NAMED_FIELD@[68; 76)
60 IDENT@[68; 73) "field" 60 NAME_REF@[68; 73)
61 COLON@[73; 74) 61 IDENT@[68; 73) "field"
62 WHITESPACE@[74; 75) 62 COLON@[73; 74)
63 LITERAL@[75; 76) 63 WHITESPACE@[74; 75)
64 INT_NUMBER@[75; 76) "0" 64 LITERAL@[75; 76)
65 R_CURLY@[76; 77) 65 INT_NUMBER@[75; 76) "0"
66 R_CURLY@[76; 77)
66 WHITESPACE@[77; 78) 67 WHITESPACE@[77; 78)
67 FAT_ARROW@[78; 80) 68 FAT_ARROW@[78; 80)
68 WHITESPACE@[80; 81) 69 WHITESPACE@[80; 81)
@@ -82,13 +83,14 @@ SOURCE_FILE@[0; 167)
82 NAME@[97; 98) 83 NAME@[97; 98)
83 IDENT@[97; 98) "Y" 84 IDENT@[97; 98) "Y"
84 WHITESPACE@[98; 99) 85 WHITESPACE@[98; 99)
85 IF_KW@[99; 101) 86 MATCH_GUARD@[99; 103)
86 WHITESPACE@[101; 102) 87 IF_KW@[99; 101)
87 PATH_EXPR@[102; 103) 88 WHITESPACE@[101; 102)
88 PATH@[102; 103) 89 PATH_EXPR@[102; 103)
89 PATH_SEGMENT@[102; 103) 90 PATH@[102; 103)
90 NAME_REF@[102; 103) 91 PATH_SEGMENT@[102; 103)
91 IDENT@[102; 103) "Z" 92 NAME_REF@[102; 103)
93 IDENT@[102; 103) "Z"
92 WHITESPACE@[103; 104) 94 WHITESPACE@[103; 104)
93 FAT_ARROW@[104; 106) 95 FAT_ARROW@[104; 106)
94 WHITESPACE@[106; 107) 96 WHITESPACE@[106; 107)
@@ -110,13 +112,14 @@ SOURCE_FILE@[0; 167)
110 NAME@[125; 126) 112 NAME@[125; 126)
111 IDENT@[125; 126) "Y" 113 IDENT@[125; 126) "Y"
112 WHITESPACE@[126; 127) 114 WHITESPACE@[126; 127)
113 IF_KW@[127; 129) 115 MATCH_GUARD@[127; 131)
114 WHITESPACE@[129; 130) 116 IF_KW@[127; 129)
115 PATH_EXPR@[130; 131) 117 WHITESPACE@[129; 130)
116 PATH@[130; 131) 118 PATH_EXPR@[130; 131)
117 PATH_SEGMENT@[130; 131) 119 PATH@[130; 131)
118 NAME_REF@[130; 131) 120 PATH_SEGMENT@[130; 131)
119 IDENT@[130; 131) "Z" 121 NAME_REF@[130; 131)
122 IDENT@[130; 131) "Z"
120 WHITESPACE@[131; 132) 123 WHITESPACE@[131; 132)
121 FAT_ARROW@[132; 134) 124 FAT_ARROW@[132; 134)
122 WHITESPACE@[134; 135) 125 WHITESPACE@[134; 135)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs
new file mode 100644
index 000000000..f1bd72fc4
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs
@@ -0,0 +1,5 @@
1fn foo() {
2 match () {
3 _ if foo => (),
4 }
5}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt
new file mode 100644
index 000000000..27553882d
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt
@@ -0,0 +1,47 @@
1SOURCE_FILE@[0; 58)
2 FN_DEF@[0; 57)
3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3)
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9)
11 BLOCK@[9; 57)
12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15)
14 MATCH_EXPR@[15; 55)
15 MATCH_KW@[15; 20)
16 WHITESPACE@[20; 21)
17 TUPLE_EXPR@[21; 23)
18 L_PAREN@[21; 22)
19 R_PAREN@[22; 23)
20 WHITESPACE@[23; 24)
21 MATCH_ARM_LIST@[24; 55)
22 L_CURLY@[24; 25)
23 WHITESPACE@[25; 34)
24 MATCH_ARM@[34; 48)
25 PLACEHOLDER_PAT@[34; 35)
26 UNDERSCORE@[34; 35)
27 WHITESPACE@[35; 36)
28 MATCH_GUARD@[36; 42)
29 IF_KW@[36; 38)
30 WHITESPACE@[38; 39)
31 PATH_EXPR@[39; 42)
32 PATH@[39; 42)
33 PATH_SEGMENT@[39; 42)
34 NAME_REF@[39; 42)
35 IDENT@[39; 42) "foo"
36 WHITESPACE@[42; 43)
37 FAT_ARROW@[43; 45)
38 WHITESPACE@[45; 46)
39 TUPLE_EXPR@[46; 48)
40 L_PAREN@[46; 47)
41 R_PAREN@[47; 48)
42 COMMA@[48; 49)
43 WHITESPACE@[49; 54)
44 R_CURLY@[54; 55)
45 WHITESPACE@[55; 56)
46 R_CURLY@[56; 57)
47 WHITESPACE@[57; 58)