aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-02-08 11:49:43 +0000
committerAleksey Kladov <[email protected]>2019-02-08 11:49:43 +0000
commit12e3b4c70b5ef23b2fdfc197296d483680e125f9 (patch)
tree71baa0e0a62f9f6b61450501c5f821f67badf9e4
parent5cb1d41a30d25cbe136402644bf5434dd667f1e5 (diff)
reformat the world
-rw-r--r--crates/gen_lsp_server/src/msg.rs39
-rw-r--r--crates/gen_lsp_server/src/stdio.rs4
-rw-r--r--crates/ra_arena/src/lib.rs20
-rw-r--r--crates/ra_arena/src/map.rs10
-rw-r--r--crates/ra_assists/src/add_derive.rs6
-rw-r--r--crates/ra_assists/src/add_impl.rs22
-rw-r--r--crates/ra_assists/src/assist_ctx.rs16
-rw-r--r--crates/ra_assists/src/change_visibility.rs42
-rw-r--r--crates/ra_assists/src/fill_match_arms.rs5
-rw-r--r--crates/ra_assists/src/introduce_variable.rs6
-rw-r--r--crates/ra_assists/src/lib.rs16
-rw-r--r--crates/ra_assists/src/replace_if_let_with_match.rs6
-rw-r--r--crates/ra_assists/src/split_import.rs4
-rw-r--r--crates/ra_cli/src/main.rs19
-rw-r--r--crates/ra_db/src/input.rs30
-rw-r--r--crates/ra_db/src/lib.rs7
-rw-r--r--crates/ra_db/src/loc2id.rs9
-rw-r--r--crates/ra_hir/src/adt.rs23
-rw-r--r--crates/ra_hir/src/code_model_api.rs71
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs12
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs9
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs10
-rw-r--r--crates/ra_hir/src/expr.rs150
-rw-r--r--crates/ra_hir/src/expr/scope.rs52
-rw-r--r--crates/ra_hir/src/generics.rs10
-rw-r--r--crates/ra_hir/src/ids.rs34
-rw-r--r--crates/ra_hir/src/impl_block.rs23
-rw-r--r--crates/ra_hir/src/macros.rs22
-rw-r--r--crates/ra_hir/src/mock.rs5
-rw-r--r--crates/ra_hir/src/module_tree.rs22
-rw-r--r--crates/ra_hir/src/nameres.rs95
-rw-r--r--crates/ra_hir/src/nameres/lower.rs31
-rw-r--r--crates/ra_hir/src/nameres/tests.rs34
-rw-r--r--crates/ra_hir/src/path.rs44
-rw-r--r--crates/ra_hir/src/query_definitions.rs4
-rw-r--r--crates/ra_hir/src/resolve.rs35
-rw-r--r--crates/ra_hir/src/source_binder.rs31
-rw-r--r--crates/ra_hir/src/ty.rs249
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs30
-rw-r--r--crates/ra_hir/src/ty/tests.rs9
-rw-r--r--crates/ra_hir/src/type_ref.rs13
-rw-r--r--crates/ra_ide_api/src/assists.rs5
-rw-r--r--crates/ra_ide_api/src/call_info.rs38
-rw-r--r--crates/ra_ide_api/src/change.rs39
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_fn_param.rs9
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs12
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs6
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs10
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs8
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs16
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs12
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs4
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs40
-rw-r--r--crates/ra_ide_api/src/hover.rs14
-rw-r--r--crates/ra_ide_api/src/impls.rs24
-rw-r--r--crates/ra_ide_api/src/lib.rs24
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs9
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs10
-rw-r--r--crates/ra_ide_api/src/references.rs4
-rw-r--r--crates/ra_ide_api/src/runnables.rs31
-rw-r--r--crates/ra_ide_api/src/status.rs21
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs5
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs16
-rw-r--r--crates/ra_ide_api_light/src/diagnostics.rs32
-rw-r--r--crates/ra_ide_api_light/src/extend_selection.rs57
-rw-r--r--crates/ra_ide_api_light/src/folding_ranges.rs47
-rw-r--r--crates/ra_ide_api_light/src/formatting.rs5
-rw-r--r--crates/ra_ide_api_light/src/join_lines.rs27
-rw-r--r--crates/ra_ide_api_light/src/lib.rs14
-rw-r--r--crates/ra_ide_api_light/src/line_index.rs165
-rw-r--r--crates/ra_ide_api_light/src/line_index_utils.rs51
-rw-r--r--crates/ra_ide_api_light/src/structure.rs13
-rw-r--r--crates/ra_ide_api_light/src/typing.rs17
-rw-r--r--crates/ra_lsp_server/src/caps.rs20
-rw-r--r--crates/ra_lsp_server/src/cargo_target_spec.rs5
-rw-r--r--crates/ra_lsp_server/src/conv.rs59
-rw-r--r--crates/ra_lsp_server/src/main.rs26
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs55
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs75
-rw-r--r--crates/ra_lsp_server/src/main_loop/subscriptions.rs4
-rw-r--r--crates/ra_lsp_server/src/project_model/cargo_workspace.rs17
-rw-r--r--crates/ra_lsp_server/src/project_model/sysroot.rs9
-rw-r--r--crates/ra_lsp_server/src/server_world.rs28
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/main.rs10
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/support.rs16
-rw-r--r--crates/ra_mbe/src/lib.rs28
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs29
-rw-r--r--crates/ra_mbe/src/mbe_parser.rs11
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs25
-rw-r--r--crates/ra_syntax/src/algo/visit.rs17
-rw-r--r--crates/ra_syntax/src/ast.rs37
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs15
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs9
-rw-r--r--crates/ra_syntax/src/grammar/items.rs6
-rw-r--r--crates/ra_syntax/src/grammar/params.rs6
-rw-r--r--crates/ra_syntax/src/grammar/patterns.rs4
-rw-r--r--crates/ra_syntax/src/lexer/ptr.rs5
-rw-r--r--crates/ra_syntax/src/lib.rs9
-rw-r--r--crates/ra_syntax/src/parser_api.rs5
-rw-r--r--crates/ra_syntax/src/parser_impl.rs22
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs41
-rw-r--r--crates/ra_syntax/src/parser_impl/input.rs6
-rw-r--r--crates/ra_syntax/src/ptr.rs19
-rw-r--r--crates/ra_syntax/src/reparsing.rs10
-rw-r--r--crates/ra_syntax/src/string_lexing/parser.rs9
-rw-r--r--crates/ra_syntax/src/string_lexing/string.rs7
-rw-r--r--crates/ra_syntax/src/validation/block.rs6
-rw-r--r--crates/ra_syntax/src/validation/byte.rs30
-rw-r--r--crates/ra_syntax/src/validation/byte_string.rs20
-rw-r--r--crates/ra_syntax/src/validation/char.rs20
-rw-r--r--crates/ra_syntax/src/validation/string.rs20
-rw-r--r--crates/ra_syntax/src/yellow/builder.rs5
-rw-r--r--crates/ra_syntax/src/yellow/syntax_error.rs12
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs10
-rw-r--r--crates/ra_syntax/tests/test.rs59
-rw-r--r--crates/ra_text_edit/src/lib.rs5
-rw-r--r--crates/ra_text_edit/src/test_utils.rs8
-rw-r--r--crates/ra_text_edit/src/text_edit.rs4
-rw-r--r--crates/ra_vfs/src/io.rs57
-rw-r--r--crates/ra_vfs/src/lib.rs86
-rw-r--r--crates/ra_vfs/tests/vfs.rs62
-rw-r--r--crates/test_utils/src/lib.rs37
-rw-r--r--crates/test_utils/src/marks.rs5
-rw-r--r--crates/thread_worker/src/lib.rs9
-rw-r--r--crates/tools/src/bin/pre-commit.rs13
-rw-r--r--crates/tools/src/lib.rs38
-rw-r--r--crates/tools/src/main.rs10
-rw-r--r--crates/tools/tests/cli.rs10
129 files changed, 728 insertions, 2510 deletions
diff --git a/crates/gen_lsp_server/src/msg.rs b/crates/gen_lsp_server/src/msg.rs
index 818111fe7..02c7a1858 100644
--- a/crates/gen_lsp_server/src/msg.rs
+++ b/crates/gen_lsp_server/src/msg.rs
@@ -80,10 +80,7 @@ impl RawMessage {
80 #[serde(flatten)] 80 #[serde(flatten)]
81 msg: RawMessage, 81 msg: RawMessage,
82 } 82 }
83 let text = to_string(&JsonRpc { 83 let text = to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?;
84 jsonrpc: "2.0",
85 msg: self,
86 })?;
87 write_msg_text(w, &text)?; 84 write_msg_text(w, &text)?;
88 Ok(()) 85 Ok(())
89 } 86 }
@@ -95,11 +92,7 @@ impl RawRequest {
95 R: Request, 92 R: Request,
96 R::Params: serde::Serialize, 93 R::Params: serde::Serialize,
97 { 94 {
98 RawRequest { 95 RawRequest { id, method: R::METHOD.to_string(), params: to_value(params).unwrap() }
99 id,
100 method: R::METHOD.to_string(),
101 params: to_value(params).unwrap(),
102 }
103 } 96 }
104 pub fn cast<R>(self) -> ::std::result::Result<(u64, R::Params), RawRequest> 97 pub fn cast<R>(self) -> ::std::result::Result<(u64, R::Params), RawRequest>
105 where 98 where
@@ -121,23 +114,11 @@ impl RawResponse {
121 R: Request, 114 R: Request,
122 R::Result: serde::Serialize, 115 R::Result: serde::Serialize,
123 { 116 {
124 RawResponse { 117 RawResponse { id, result: Some(to_value(&result).unwrap()), error: None }
125 id,
126 result: Some(to_value(&result).unwrap()),
127 error: None,
128 }
129 } 118 }
130 pub fn err(id: u64, code: i32, message: String) -> RawResponse { 119 pub fn err(id: u64, code: i32, message: String) -> RawResponse {
131 let error = RawResponseError { 120 let error = RawResponseError { code, message, data: None };
132 code, 121 RawResponse { id, result: None, error: Some(error) }
133 message,
134 data: None,
135 };
136 RawResponse {
137 id,
138 result: None,
139 error: Some(error),
140 }
141 } 122 }
142} 123}
143 124
@@ -147,10 +128,7 @@ impl RawNotification {
147 N: Notification, 128 N: Notification,
148 N::Params: serde::Serialize, 129 N::Params: serde::Serialize,
149 { 130 {
150 RawNotification { 131 RawNotification { method: N::METHOD.to_string(), params: to_value(params).unwrap() }
151 method: N::METHOD.to_string(),
152 params: to_value(params).unwrap(),
153 }
154 } 132 }
155 pub fn is<N>(&self) -> bool 133 pub fn is<N>(&self) -> bool
156 where 134 where
@@ -187,9 +165,8 @@ fn read_msg_text(inp: &mut impl BufRead) -> Result<Option<String>> {
187 } 165 }
188 let mut parts = buf.splitn(2, ": "); 166 let mut parts = buf.splitn(2, ": ");
189 let header_name = parts.next().unwrap(); 167 let header_name = parts.next().unwrap();
190 let header_value = parts 168 let header_value =
191 .next() 169 parts.next().ok_or_else(|| format_err!("malformed header: {:?}", buf))?;
192 .ok_or_else(|| format_err!("malformed header: {:?}", buf))?;
193 if header_name == "Content-Length" { 170 if header_name == "Content-Length" {
194 size = Some(header_value.parse::<usize>()?); 171 size = Some(header_value.parse::<usize>()?);
195 } 172 }
diff --git a/crates/gen_lsp_server/src/stdio.rs b/crates/gen_lsp_server/src/stdio.rs
index 5c8e33854..dab2d8da8 100644
--- a/crates/gen_lsp_server/src/stdio.rs
+++ b/crates/gen_lsp_server/src/stdio.rs
@@ -13,9 +13,7 @@ pub fn stdio_transport() -> (Receiver<RawMessage>, Sender<RawMessage>, Threads)
13 let writer = thread::spawn(move || { 13 let writer = thread::spawn(move || {
14 let stdout = stdout(); 14 let stdout = stdout();
15 let mut stdout = stdout.lock(); 15 let mut stdout = stdout.lock();
16 writer_receiver 16 writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout))?;
17 .into_iter()
18 .try_for_each(|it| it.write(&mut stdout))?;
19 Ok(()) 17 Ok(())
20 }); 18 });
21 let (reader_sender, reader_receiver) = bounded::<RawMessage>(16); 19 let (reader_sender, reader_receiver) = bounded::<RawMessage>(16);
diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs
index 97f554838..1c97c2662 100644
--- a/crates/ra_arena/src/lib.rs
+++ b/crates/ra_arena/src/lib.rs
@@ -44,10 +44,7 @@ pub struct Arena<ID: ArenaId, T> {
44 44
45impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> { 45impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> {
46 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 46 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
47 fmt.debug_struct("Arena") 47 fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish()
48 .field("len", &self.len())
49 .field("data", &self.data)
50 .finish()
51 } 48 }
52} 49}
53 50
@@ -80,19 +77,13 @@ impl<ID: ArenaId, T> Arena<ID, T> {
80 ID::from_raw(id) 77 ID::from_raw(id)
81 } 78 }
82 pub fn iter<'a>(&'a self) -> impl Iterator<Item = (ID, &'a T)> { 79 pub fn iter<'a>(&'a self) -> impl Iterator<Item = (ID, &'a T)> {
83 self.data 80 self.data.iter().enumerate().map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
84 .iter()
85 .enumerate()
86 .map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
87 } 81 }
88} 82}
89 83
90impl<ID: ArenaId, T> Default for Arena<ID, T> { 84impl<ID: ArenaId, T> Default for Arena<ID, T> {
91 fn default() -> Arena<ID, T> { 85 fn default() -> Arena<ID, T> {
92 Arena { 86 Arena { data: Vec::new(), _ty: PhantomData }
93 data: Vec::new(),
94 _ty: PhantomData,
95 }
96 } 87 }
97} 88}
98 89
@@ -116,9 +107,6 @@ impl<ID: ArenaId, T> FromIterator<T> for Arena<ID, T> {
116 where 107 where
117 I: IntoIterator<Item = T>, 108 I: IntoIterator<Item = T>,
118 { 109 {
119 Arena { 110 Arena { data: Vec::from_iter(iter), _ty: PhantomData }
120 data: Vec::from_iter(iter),
121 _ty: PhantomData,
122 }
123 } 111 }
124} 112}
diff --git a/crates/ra_arena/src/map.rs b/crates/ra_arena/src/map.rs
index be80edaf3..b73d4e365 100644
--- a/crates/ra_arena/src/map.rs
+++ b/crates/ra_arena/src/map.rs
@@ -42,10 +42,7 @@ impl<ID: ArenaId, T> ArenaMap<ID, T> {
42 } 42 }
43 43
44 pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> { 44 pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
45 self.v 45 self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
46 .iter()
47 .enumerate()
48 .filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
49 } 46 }
50 47
51 fn to_idx(id: ID) -> usize { 48 fn to_idx(id: ID) -> usize {
@@ -66,9 +63,6 @@ impl<ID: ArenaId, T> std::ops::Index<ID> for ArenaMap<ID, T> {
66 63
67impl<ID, T> Default for ArenaMap<ID, T> { 64impl<ID, T> Default for ArenaMap<ID, T> {
68 fn default() -> Self { 65 fn default() -> Self {
69 ArenaMap { 66 ArenaMap { v: Vec::new(), _ty: PhantomData }
70 v: Vec::new(),
71 _ty: PhantomData,
72 }
73 } 67 }
74} 68}
diff --git a/crates/ra_assists/src/add_derive.rs b/crates/ra_assists/src/add_derive.rs
index 01a4079f6..caf21e079 100644
--- a/crates/ra_assists/src/add_derive.rs
+++ b/crates/ra_assists/src/add_derive.rs
@@ -30,10 +30,8 @@ pub(crate) fn add_derive(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
30 30
31// Insert `derive` after doc comments. 31// Insert `derive` after doc comments.
32fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> { 32fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> {
33 let non_ws_child = nominal 33 let non_ws_child =
34 .syntax() 34 nominal.syntax().children().find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
35 .children()
36 .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
37 Some(non_ws_child.range().start()) 35 Some(non_ws_child.range().start())
38} 36}
39 37
diff --git a/crates/ra_assists/src/add_impl.rs b/crates/ra_assists/src/add_impl.rs
index 699508f91..f2360bc89 100644
--- a/crates/ra_assists/src/add_impl.rs
+++ b/crates/ra_assists/src/add_impl.rs
@@ -21,17 +21,11 @@ pub(crate) fn add_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
21 buf.push_str(" "); 21 buf.push_str(" ");
22 buf.push_str(name.text().as_str()); 22 buf.push_str(name.text().as_str());
23 if let Some(type_params) = type_params { 23 if let Some(type_params) = type_params {
24 let lifetime_params = type_params 24 let lifetime_params =
25 .lifetime_params() 25 type_params.lifetime_params().filter_map(|it| it.lifetime()).map(|it| it.text());
26 .filter_map(|it| it.lifetime()) 26 let type_params =
27 .map(|it| it.text()); 27 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text());
28 let type_params = type_params 28 join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf);
29 .type_params()
30 .filter_map(|it| it.name())
31 .map(|it| it.text());
32 join(lifetime_params.chain(type_params))
33 .surround_with("<", ">")
34 .to_buf(&mut buf);
35 } 29 }
36 buf.push_str(" {\n"); 30 buf.push_str(" {\n");
37 edit.set_cursor(start_offset + TextUnit::of_str(&buf)); 31 edit.set_cursor(start_offset + TextUnit::of_str(&buf));
@@ -47,11 +41,7 @@ mod tests {
47 41
48 #[test] 42 #[test]
49 fn test_add_impl() { 43 fn test_add_impl() {
50 check_assist( 44 check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n<|>\n}\n");
51 add_impl,
52 "struct Foo {<|>}\n",
53 "struct Foo {}\n\nimpl Foo {\n<|>\n}\n",
54 );
55 check_assist( 45 check_assist(
56 add_impl, 46 add_impl,
57 "struct Foo<T: Clone> {<|>}", 47 "struct Foo<T: Clone> {<|>}",
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index 6d09bde52..0bf640241 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -69,12 +69,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
69 F: FnOnce(AssistCtx<DB>) -> T, 69 F: FnOnce(AssistCtx<DB>) -> T,
70 { 70 {
71 let source_file = &db.parse(frange.file_id); 71 let source_file = &db.parse(frange.file_id);
72 let ctx = AssistCtx { 72 let ctx = AssistCtx { db, frange, source_file, should_compute_edit };
73 db,
74 frange,
75 source_file,
76 should_compute_edit,
77 };
78 f(ctx) 73 f(ctx)
79 } 74 }
80 75
@@ -83,9 +78,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
83 label: impl Into<String>, 78 label: impl Into<String>,
84 f: impl FnOnce(&mut AssistBuilder), 79 f: impl FnOnce(&mut AssistBuilder),
85 ) -> Option<Assist> { 80 ) -> Option<Assist> {
86 let label = AssistLabel { 81 let label = AssistLabel { label: label.into() };
87 label: label.into(),
88 };
89 if !self.should_compute_edit { 82 if !self.should_compute_edit {
90 return Some(Assist::Unresolved(label)); 83 return Some(Assist::Unresolved(label));
91 } 84 }
@@ -146,9 +139,6 @@ impl AssistBuilder {
146 } 139 }
147 140
148 fn build(self) -> AssistAction { 141 fn build(self) -> AssistAction {
149 AssistAction { 142 AssistAction { edit: self.edit.finish(), cursor_position: self.cursor_position }
150 edit: self.edit.finish(),
151 cursor_position: self.cursor_position,
152 }
153 } 143 }
154} 144}
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index 4cd32985e..fa5f231c8 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -81,31 +81,11 @@ mod tests {
81 81
82 #[test] 82 #[test]
83 fn change_visibility_adds_pub_crate_to_items() { 83 fn change_visibility_adds_pub_crate_to_items() {
84 check_assist( 84 check_assist(change_visibility, "<|>fn foo() {}", "<|>pub(crate) fn foo() {}");
85 change_visibility, 85 check_assist(change_visibility, "f<|>n foo() {}", "<|>pub(crate) fn foo() {}");
86 "<|>fn foo() {}", 86 check_assist(change_visibility, "<|>struct Foo {}", "<|>pub(crate) struct Foo {}");
87 "<|>pub(crate) fn foo() {}", 87 check_assist(change_visibility, "<|>mod foo {}", "<|>pub(crate) mod foo {}");
88 ); 88 check_assist(change_visibility, "<|>trait Foo {}", "<|>pub(crate) trait Foo {}");
89 check_assist(
90 change_visibility,
91 "f<|>n foo() {}",
92 "<|>pub(crate) fn foo() {}",
93 );
94 check_assist(
95 change_visibility,
96 "<|>struct Foo {}",
97 "<|>pub(crate) struct Foo {}",
98 );
99 check_assist(
100 change_visibility,
101 "<|>mod foo {}",
102 "<|>pub(crate) mod foo {}",
103 );
104 check_assist(
105 change_visibility,
106 "<|>trait Foo {}",
107 "<|>pub(crate) trait Foo {}",
108 );
109 check_assist(change_visibility, "m<|>od {}", "<|>pub(crate) mod {}"); 89 check_assist(change_visibility, "m<|>od {}", "<|>pub(crate) mod {}");
110 check_assist( 90 check_assist(
111 change_visibility, 91 change_visibility,
@@ -125,20 +105,12 @@ mod tests {
125 105
126 #[test] 106 #[test]
127 fn change_visibility_pub_to_pub_crate() { 107 fn change_visibility_pub_to_pub_crate() {
128 check_assist( 108 check_assist(change_visibility, "<|>pub fn foo() {}", "<|>pub(crate) fn foo() {}")
129 change_visibility,
130 "<|>pub fn foo() {}",
131 "<|>pub(crate) fn foo() {}",
132 )
133 } 109 }
134 110
135 #[test] 111 #[test]
136 fn change_visibility_pub_crate_to_pub() { 112 fn change_visibility_pub_crate_to_pub() {
137 check_assist( 113 check_assist(change_visibility, "<|>pub(crate) fn foo() {}", "<|>pub fn foo() {}")
138 change_visibility,
139 "<|>pub(crate) fn foo() {}",
140 "<|>pub fn foo() {}",
141 )
142 } 114 }
143 115
144 #[test] 116 #[test]
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index 9aa37d94c..741f75e2a 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -27,10 +27,7 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
27 let node_expr = syntax_mapping.node_expr(expr)?; 27 let node_expr = syntax_mapping.node_expr(expr)?;
28 let match_expr_ty = infer_result[node_expr].clone(); 28 let match_expr_ty = infer_result[node_expr].clone();
29 let enum_def = match match_expr_ty { 29 let enum_def = match match_expr_ty {
30 Ty::Adt { 30 Ty::Adt { def_id: AdtDef::Enum(e), .. } => e,
31 def_id: AdtDef::Enum(e),
32 ..
33 } => e,
34 _ => return None, 31 _ => return None,
35 }; 32 };
36 let enum_name = enum_def.name(ctx.db)?; 33 let enum_name = enum_def.name(ctx.db)?;
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs
index f587b4fe6..4f7c9f3c2 100644
--- a/crates/ra_assists/src/introduce_variable.rs
+++ b/crates/ra_assists/src/introduce_variable.rs
@@ -81,11 +81,7 @@ fn anchor_stmt(expr: &ast::Expr) -> Option<(&SyntaxNode, bool)> {
81 return Some((node, false)); 81 return Some((node, false));
82 } 82 }
83 83
84 if let Some(expr) = node 84 if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) {
85 .parent()
86 .and_then(ast::Block::cast)
87 .and_then(|it| it.expr())
88 {
89 if expr.syntax() == node { 85 if expr.syntax() == node {
90 return Some((node, false)); 86 return Some((node, false));
91 } 87 }
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 555af51bc..881db6347 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -89,9 +89,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
89} 89}
90 90
91fn non_trivia_sibling(node: &SyntaxNode, direction: Direction) -> Option<&SyntaxNode> { 91fn non_trivia_sibling(node: &SyntaxNode, direction: Direction) -> Option<&SyntaxNode> {
92 node.siblings(direction) 92 node.siblings(direction).skip(1).find(|node| !node.kind().is_trivia())
93 .skip(1)
94 .find(|node| !node.kind().is_trivia())
95} 93}
96 94
97#[cfg(test)] 95#[cfg(test)]
@@ -110,10 +108,8 @@ mod helpers {
110 ) { 108 ) {
111 let (before_cursor_pos, before) = extract_offset(before); 109 let (before_cursor_pos, before) = extract_offset(before);
112 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 110 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
113 let frange = FileRange { 111 let frange =
114 file_id, 112 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
115 range: TextRange::offset_len(before_cursor_pos, 0.into()),
116 };
117 let assist = 113 let assist =
118 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); 114 AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
119 let action = match assist { 115 let action = match assist {
@@ -161,10 +157,8 @@ mod helpers {
161 ) { 157 ) {
162 let (before_cursor_pos, before) = extract_offset(before); 158 let (before_cursor_pos, before) = extract_offset(before);
163 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); 159 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
164 let frange = FileRange { 160 let frange =
165 file_id, 161 FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
166 range: TextRange::offset_len(before_cursor_pos, 0.into()),
167 };
168 let assist = AssistCtx::with_ctx(&db, frange, true, assist); 162 let assist = AssistCtx::with_ctx(&db, frange, true, assist);
169 assert!(assist.is_none()); 163 assert!(assist.is_none());
170 } 164 }
diff --git a/crates/ra_assists/src/replace_if_let_with_match.rs b/crates/ra_assists/src/replace_if_let_with_match.rs
index f6af47ec9..683f0d119 100644
--- a/crates/ra_assists/src/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/replace_if_let_with_match.rs
@@ -30,11 +30,7 @@ fn build_match_expr(
30) -> String { 30) -> String {
31 let mut buf = String::new(); 31 let mut buf = String::new();
32 buf.push_str(&format!("match {} {{\n", expr.syntax().text())); 32 buf.push_str(&format!("match {} {{\n", expr.syntax().text()));
33 buf.push_str(&format!( 33 buf.push_str(&format!(" {} => {}\n", pat1.syntax().text(), format_arm(arm1)));
34 " {} => {}\n",
35 pat1.syntax().text(),
36 format_arm(arm1)
37 ));
38 buf.push_str(&format!(" _ => {}\n", format_arm(arm2))); 34 buf.push_str(&format!(" _ => {}\n", format_arm(arm2)));
39 buf.push_str("}"); 35 buf.push_str("}");
40 buf 36 buf
diff --git a/crates/ra_assists/src/split_import.rs b/crates/ra_assists/src/split_import.rs
index 7e34be087..fb69cef9c 100644
--- a/crates/ra_assists/src/split_import.rs
+++ b/crates/ra_assists/src/split_import.rs
@@ -8,9 +8,7 @@ use ra_syntax::{
8use crate::{AssistCtx, Assist}; 8use crate::{AssistCtx, Assist};
9 9
10pub(crate) fn split_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10pub(crate) fn split_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let colon_colon = ctx 11 let colon_colon = ctx.leaf_at_offset().find(|leaf| leaf.kind() == COLONCOLON)?;
12 .leaf_at_offset()
13 .find(|leaf| leaf.kind() == COLONCOLON)?;
14 let path = colon_colon.parent().and_then(ast::Path::cast)?; 12 let path = colon_colon.parent().and_then(ast::Path::cast)?;
15 let top_path = generate(Some(path), |it| it.parent_path()).last()?; 13 let top_path = generate(Some(path), |it| it.parent_path()).last()?;
16 14
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 6b5be27be..a4debeb48 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -13,18 +13,8 @@ fn main() -> Result<()> {
13 .setting(clap::AppSettings::SubcommandRequiredElseHelp) 13 .setting(clap::AppSettings::SubcommandRequiredElseHelp)
14 .subcommand( 14 .subcommand(
15 SubCommand::with_name("render-test") 15 SubCommand::with_name("render-test")
16 .arg( 16 .arg(Arg::with_name("line").long("--line").required(true).takes_value(true))
17 Arg::with_name("line") 17 .arg(Arg::with_name("file").long("--file").required(true).takes_value(true)),
18 .long("--line")
19 .required(true)
20 .takes_value(true),
21 )
22 .arg(
23 Arg::with_name("file")
24 .long("--file")
25 .required(true)
26 .takes_value(true),
27 ),
28 ) 18 )
29 .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) 19 .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump")))
30 .subcommand(SubCommand::with_name("symbols")) 20 .subcommand(SubCommand::with_name("symbols"))
@@ -108,8 +98,5 @@ fn selections(file: &SourceFile, start: u32, end: u32) -> String {
108 .iter() 98 .iter()
109 .map(|r| (1 + u32::from(r.start()), 1 + u32::from(r.end()))) 99 .map(|r| (1 + u32::from(r.start()), 1 + u32::from(r.end())))
110 .map(|(s, e)| format!("({} {})", s, e)); 100 .map(|(s, e)| format!("({} {})", s, e));
111 join(ranges) 101 join(ranges).separator(" ").surround_with("(", ")").to_string()
112 .separator(" ")
113 .surround_with("(", ")")
114 .to_string()
115} 102}
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index 275894252..614325a0f 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -64,10 +64,7 @@ struct CrateData {
64 64
65impl CrateData { 65impl CrateData {
66 fn new(file_id: FileId) -> CrateData { 66 fn new(file_id: FileId) -> CrateData {
67 CrateData { 67 CrateData { file_id, dependencies: Vec::new() }
68 file_id,
69 dependencies: Vec::new(),
70 }
71 } 68 }
72 69
73 fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) { 70 fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) {
@@ -112,10 +109,7 @@ impl CrateGraph {
112 self.arena[&crate_id].file_id 109 self.arena[&crate_id].file_id
113 } 110 }
114 pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { 111 pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
115 let (&crate_id, _) = self 112 let (&crate_id, _) = self.arena.iter().find(|(_crate_id, data)| data.file_id == file_id)?;
116 .arena
117 .iter()
118 .find(|(_crate_id, data)| data.file_id == file_id)?;
119 Some(crate_id) 113 Some(crate_id)
120 } 114 }
121 pub fn dependencies<'a>( 115 pub fn dependencies<'a>(
@@ -153,15 +147,9 @@ mod tests {
153 let crate1 = graph.add_crate_root(FileId(1u32)); 147 let crate1 = graph.add_crate_root(FileId(1u32));
154 let crate2 = graph.add_crate_root(FileId(2u32)); 148 let crate2 = graph.add_crate_root(FileId(2u32));
155 let crate3 = graph.add_crate_root(FileId(3u32)); 149 let crate3 = graph.add_crate_root(FileId(3u32));
156 assert!(graph 150 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
157 .add_dep(crate1, SmolStr::new("crate2"), crate2) 151 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
158 .is_ok()); 152 assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err());
159 assert!(graph
160 .add_dep(crate2, SmolStr::new("crate3"), crate3)
161 .is_ok());
162 assert!(graph
163 .add_dep(crate3, SmolStr::new("crate1"), crate1)
164 .is_err());
165 } 153 }
166 154
167 #[test] 155 #[test]
@@ -170,11 +158,7 @@ mod tests {
170 let crate1 = graph.add_crate_root(FileId(1u32)); 158 let crate1 = graph.add_crate_root(FileId(1u32));
171 let crate2 = graph.add_crate_root(FileId(2u32)); 159 let crate2 = graph.add_crate_root(FileId(2u32));
172 let crate3 = graph.add_crate_root(FileId(3u32)); 160 let crate3 = graph.add_crate_root(FileId(3u32));
173 assert!(graph 161 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
174 .add_dep(crate1, SmolStr::new("crate2"), crate2) 162 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
175 .is_ok());
176 assert!(graph
177 .add_dep(crate2, SmolStr::new("crate3"), crate3)
178 .is_ok());
179 } 163 }
180} 164}
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 66634e05b..31442713d 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -94,11 +94,8 @@ pub trait SourceDatabase: CheckCanceled + std::fmt::Debug {
94fn source_root_crates(db: &impl SourceDatabase, id: SourceRootId) -> Arc<Vec<CrateId>> { 94fn source_root_crates(db: &impl SourceDatabase, id: SourceRootId) -> Arc<Vec<CrateId>> {
95 let root = db.source_root(id); 95 let root = db.source_root(id);
96 let graph = db.crate_graph(); 96 let graph = db.crate_graph();
97 let res = root 97 let res =
98 .files 98 root.files.values().filter_map(|&it| graph.crate_id_for_crate_root(it)).collect::<Vec<_>>();
99 .values()
100 .filter_map(|&it| graph.crate_id_for_crate_root(it))
101 .collect::<Vec<_>>();
102 Arc::new(res) 99 Arc::new(res)
103} 100}
104 101
diff --git a/crates/ra_db/src/loc2id.rs b/crates/ra_db/src/loc2id.rs
index 359cd893d..d27fa7682 100644
--- a/crates/ra_db/src/loc2id.rs
+++ b/crates/ra_db/src/loc2id.rs
@@ -30,10 +30,7 @@ where
30 LOC: Clone + Eq + Hash, 30 LOC: Clone + Eq + Hash,
31{ 31{
32 fn default() -> Self { 32 fn default() -> Self {
33 Loc2IdMap { 33 Loc2IdMap { id2loc: Arena::default(), loc2id: FxHashMap::default() }
34 id2loc: Arena::default(),
35 loc2id: FxHashMap::default(),
36 }
37 } 34 }
38} 35}
39 36
@@ -85,9 +82,7 @@ where
85 LOC: Clone + Eq + Hash, 82 LOC: Clone + Eq + Hash,
86{ 83{
87 fn default() -> Self { 84 fn default() -> Self {
88 LocationIntener { 85 LocationIntener { map: Default::default() }
89 map: Default::default(),
90 }
91 } 86 }
92} 87}
93 88
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index c549e2126..6d917bb1b 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -62,10 +62,7 @@ impl StructData {
62} 62}
63 63
64fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = &ast::EnumVariant> { 64fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = &ast::EnumVariant> {
65 enum_def 65 enum_def.variant_list().into_iter().flat_map(|it| it.variants())
66 .variant_list()
67 .into_iter()
68 .flat_map(|it| it.variants())
69} 66}
70 67
71impl EnumVariant { 68impl EnumVariant {
@@ -83,9 +80,7 @@ impl EnumVariant {
83 (file_id, var) 80 (file_id, var)
84 } 81 }
85 pub(crate) fn variant_data(&self, db: &impl PersistentHirDatabase) -> Arc<VariantData> { 82 pub(crate) fn variant_data(&self, db: &impl PersistentHirDatabase) -> Arc<VariantData> {
86 db.enum_data(self.parent).variants[self.id] 83 db.enum_data(self.parent).variants[self.id].variant_data.clone()
87 .variant_data
88 .clone()
89 } 84 }
90} 85}
91 86
@@ -222,14 +217,12 @@ impl StructField {
222 }; 217 };
223 218
224 let field_sources = match struct_flavor { 219 let field_sources = match struct_flavor {
225 ast::StructFlavor::Tuple(fl) => fl 220 ast::StructFlavor::Tuple(fl) => {
226 .fields() 221 fl.fields().map(|it| FieldSource::Pos(it.to_owned())).collect()
227 .map(|it| FieldSource::Pos(it.to_owned())) 222 }
228 .collect(), 223 ast::StructFlavor::Named(fl) => {
229 ast::StructFlavor::Named(fl) => fl 224 fl.fields().map(|it| FieldSource::Named(it.to_owned())).collect()
230 .fields() 225 }
231 .map(|it| FieldSource::Named(it.to_owned()))
232 .collect(),
233 ast::StructFlavor::Unit => Vec::new(), 226 ast::StructFlavor::Unit => Vec::new(),
234 }; 227 };
235 let field = field_sources 228 let field = field_sources
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index a58bf8f87..cafc5279d 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -71,17 +71,7 @@ pub enum ModuleDef {
71 Trait(Trait), 71 Trait(Trait),
72 Type(Type), 72 Type(Type),
73} 73}
74impl_froms!( 74impl_froms!(ModuleDef: Module, Function, Struct, Enum, EnumVariant, Const, Static, Trait, Type);
75 ModuleDef: Module,
76 Function,
77 Struct,
78 Enum,
79 EnumVariant,
80 Const,
81 Static,
82 Trait,
83 Type
84);
85 75
86pub enum ModuleSource { 76pub enum ModuleSource {
87 SourceFile(TreeArc<ast::SourceFile>), 77 SourceFile(TreeArc<ast::SourceFile>),
@@ -90,13 +80,8 @@ pub enum ModuleSource {
90 80
91#[derive(Clone, Debug, Hash, PartialEq, Eq)] 81#[derive(Clone, Debug, Hash, PartialEq, Eq)]
92pub enum Problem { 82pub enum Problem {
93 UnresolvedModule { 83 UnresolvedModule { candidate: RelativePathBuf },
94 candidate: RelativePathBuf, 84 NotDirOwner { move_to: RelativePathBuf, candidate: RelativePathBuf },
95 },
96 NotDirOwner {
97 move_to: RelativePathBuf,
98 candidate: RelativePathBuf,
99 },
100} 85}
101 86
102impl Module { 87impl Module {
@@ -187,8 +172,7 @@ impl Module {
187 172
188impl Docs for Module { 173impl Docs for Module {
189 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> { 174 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
190 self.declaration_source(db) 175 self.declaration_source(db).and_then(|it| docs_from_ast(&*it.1))
191 .and_then(|it| docs_from_ast(&*it.1))
192 } 176 }
193} 177}
194 178
@@ -206,9 +190,7 @@ pub enum FieldSource {
206 190
207impl StructField { 191impl StructField {
208 pub fn name(&self, db: &impl HirDatabase) -> Name { 192 pub fn name(&self, db: &impl HirDatabase) -> Name {
209 self.parent.variant_data(db).fields().unwrap()[self.id] 193 self.parent.variant_data(db).fields().unwrap()[self.id].name.clone()
210 .name
211 .clone()
212 } 194 }
213 195
214 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, FieldSource) { 196 pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, FieldSource) {
@@ -257,10 +239,7 @@ impl Struct {
257 .fields() 239 .fields()
258 .into_iter() 240 .into_iter()
259 .flat_map(|it| it.iter()) 241 .flat_map(|it| it.iter())
260 .map(|(id, _)| StructField { 242 .map(|(id, _)| StructField { parent: (*self).into(), id })
261 parent: (*self).into(),
262 id,
263 })
264 .collect() 243 .collect()
265 } 244 }
266 245
@@ -271,10 +250,7 @@ impl Struct {
271 .into_iter() 250 .into_iter()
272 .flat_map(|it| it.iter()) 251 .flat_map(|it| it.iter())
273 .find(|(_id, data)| data.name == *name) 252 .find(|(_id, data)| data.name == *name)
274 .map(|(id, _)| StructField { 253 .map(|(id, _)| StructField { parent: (*self).into(), id })
275 parent: (*self).into(),
276 id,
277 })
278 } 254 }
279 255
280 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { 256 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
@@ -292,11 +268,7 @@ impl Struct {
292 let r = self.module(db).resolver(db); 268 let r = self.module(db).resolver(db);
293 // ...and add generic params, if present 269 // ...and add generic params, if present
294 let p = self.generic_params(db); 270 let p = self.generic_params(db);
295 let r = if !p.params.is_empty() { 271 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
296 r.push_generic_params_scope(p)
297 } else {
298 r
299 };
300 r 272 r
301 } 273 }
302} 274}
@@ -356,11 +328,7 @@ impl Enum {
356 let r = self.module(db).resolver(db); 328 let r = self.module(db).resolver(db);
357 // ...and add generic params, if present 329 // ...and add generic params, if present
358 let p = self.generic_params(db); 330 let p = self.generic_params(db);
359 let r = if !p.params.is_empty() { 331 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
360 r.push_generic_params_scope(p)
361 } else {
362 r
363 };
364 r 332 r
365 } 333 }
366} 334}
@@ -400,10 +368,7 @@ impl EnumVariant {
400 .fields() 368 .fields()
401 .into_iter() 369 .into_iter()
402 .flat_map(|it| it.iter()) 370 .flat_map(|it| it.iter())
403 .map(|(id, _)| StructField { 371 .map(|(id, _)| StructField { parent: (*self).into(), id })
404 parent: (*self).into(),
405 id,
406 })
407 .collect() 372 .collect()
408 } 373 }
409 374
@@ -413,10 +378,7 @@ impl EnumVariant {
413 .into_iter() 378 .into_iter()
414 .flat_map(|it| it.iter()) 379 .flat_map(|it| it.iter())
415 .find(|(_id, data)| data.name == *name) 380 .find(|(_id, data)| data.name == *name)
416 .map(|(id, _)| StructField { 381 .map(|(id, _)| StructField { parent: (*self).into(), id })
417 parent: (*self).into(),
418 id,
419 })
420 } 382 }
421} 383}
422 384
@@ -488,10 +450,7 @@ impl Function {
488 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { 450 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
489 let scopes = db.expr_scopes(*self); 451 let scopes = db.expr_scopes(*self);
490 let syntax_mapping = db.body_syntax_mapping(*self); 452 let syntax_mapping = db.body_syntax_mapping(*self);
491 ScopesWithSyntaxMapping { 453 ScopesWithSyntaxMapping { scopes, syntax_mapping }
492 scopes,
493 syntax_mapping,
494 }
495 } 454 }
496 455
497 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { 456 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
@@ -516,11 +475,7 @@ impl Function {
516 .unwrap_or_else(|| self.module(db).resolver(db)); 475 .unwrap_or_else(|| self.module(db).resolver(db));
517 // ...and add generic params, if present 476 // ...and add generic params, if present
518 let p = self.generic_params(db); 477 let p = self.generic_params(db);
519 let r = if !p.params.is_empty() { 478 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
520 r.push_generic_params_scope(p)
521 } else {
522 r
523 };
524 r 479 r
525 } 480 }
526} 481}
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index 8326c02c7..b9438fdb7 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -25,10 +25,7 @@ impl FnSignature {
25 func: Function, 25 func: Function,
26 ) -> Arc<FnSignature> { 26 ) -> Arc<FnSignature> {
27 let (_, node) = func.source(db); 27 let (_, node) = func.source(db);
28 let name = node 28 let name = node.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
29 .name()
30 .map(|n| n.as_name())
31 .unwrap_or_else(Name::missing);
32 let mut params = Vec::new(); 29 let mut params = Vec::new();
33 let mut has_self_param = false; 30 let mut has_self_param = false;
34 if let Some(param_list) = node.param_list() { 31 if let Some(param_list) = node.param_list() {
@@ -61,12 +58,7 @@ impl FnSignature {
61 TypeRef::unit() 58 TypeRef::unit()
62 }; 59 };
63 60
64 let sig = FnSignature { 61 let sig = FnSignature { name, params, ret_type, has_self_param };
65 name,
66 params,
67 ret_type,
68 has_self_param,
69 };
70 Arc::new(sig) 62 Arc::new(sig)
71 } 63 }
72} 64}
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs
index 1517434b8..161ae6e18 100644
--- a/crates/ra_hir/src/code_model_impl/krate.rs
+++ b/crates/ra_hir/src/code_model_impl/krate.rs
@@ -11,9 +11,7 @@ impl Crate {
11 crate_graph 11 crate_graph
12 .dependencies(self.crate_id) 12 .dependencies(self.crate_id)
13 .map(|dep| { 13 .map(|dep| {
14 let krate = Crate { 14 let krate = Crate { crate_id: dep.crate_id() };
15 crate_id: dep.crate_id(),
16 };
17 let name = dep.as_name(); 15 let name = dep.as_name();
18 CrateDependency { krate, name } 16 CrateDependency { krate, name }
19 }) 17 })
@@ -23,10 +21,7 @@ impl Crate {
23 let module_tree = db.module_tree(*self); 21 let module_tree = db.module_tree(*self);
24 let module_id = module_tree.modules().next()?; 22 let module_id = module_tree.modules().next()?;
25 23
26 let module = Module { 24 let module = Module { krate: *self, module_id };
27 krate: *self,
28 module_id,
29 };
30 Some(module) 25 Some(module)
31 } 26 }
32} 27}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index f487b8532..1425fa693 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -12,10 +12,7 @@ use crate::{
12 12
13impl Module { 13impl Module {
14 fn with_module_id(&self, module_id: ModuleId) -> Module { 14 fn with_module_id(&self, module_id: ModuleId) -> Module {
15 Module { 15 Module { module_id, krate: self.krate }
16 module_id,
17 krate: self.krate,
18 }
19 } 16 }
20 17
21 pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> { 18 pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> {
@@ -42,10 +39,7 @@ impl Module {
42 ) -> Option<(FileId, TreeArc<ast::Module>)> { 39 ) -> Option<(FileId, TreeArc<ast::Module>)> {
43 let module_tree = db.module_tree(self.krate); 40 let module_tree = db.module_tree(self.krate);
44 let link = self.module_id.parent_link(&module_tree)?; 41 let link = self.module_id.parent_link(&module_tree)?;
45 let file_id = link 42 let file_id = link.owner(&module_tree).file_id(&module_tree).as_original_file();
46 .owner(&module_tree)
47 .file_id(&module_tree)
48 .as_original_file();
49 let src = link.source(&module_tree, db); 43 let src = link.source(&module_tree, db);
50 Some((file_id, src)) 44 Some((file_id, src))
51 } 45 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 6826e966b..4e61d87ff 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -121,9 +121,7 @@ impl BodySyntaxMapping {
121 } 121 }
122 122
123 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 123 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
124 self.expr_syntax_mapping 124 self.expr_syntax_mapping.get(&SyntaxNodePtr::new(node.syntax())).cloned()
125 .get(&SyntaxNodePtr::new(node.syntax()))
126 .cloned()
127 } 125 }
128 126
129 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> { 127 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> {
@@ -135,9 +133,7 @@ impl BodySyntaxMapping {
135 } 133 }
136 134
137 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 135 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
138 self.pat_syntax_mapping 136 self.pat_syntax_mapping.get(&SyntaxNodePtr::new(node.syntax())).cloned()
139 .get(&SyntaxNodePtr::new(node.syntax()))
140 .cloned()
141 } 137 }
142 138
143 pub fn body(&self) -> &Arc<Body> { 139 pub fn body(&self) -> &Arc<Body> {
@@ -262,11 +258,7 @@ pub struct StructLitField {
262 258
263#[derive(Debug, Clone, Eq, PartialEq)] 259#[derive(Debug, Clone, Eq, PartialEq)]
264pub enum Statement { 260pub enum Statement {
265 Let { 261 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> },
266 pat: PatId,
267 type_ref: Option<TypeRef>,
268 initializer: Option<ExprId>,
269 },
270 Expr(ExprId), 262 Expr(ExprId),
271} 263}
272 264
@@ -275,11 +267,7 @@ impl Expr {
275 match self { 267 match self {
276 Expr::Missing => {} 268 Expr::Missing => {}
277 Expr::Path(_) => {} 269 Expr::Path(_) => {}
278 Expr::If { 270 Expr::If { condition, then_branch, else_branch } => {
279 condition,
280 then_branch,
281 else_branch,
282 } => {
283 f(*condition); 271 f(*condition);
284 f(*then_branch); 272 f(*then_branch);
285 if let Some(else_branch) = else_branch { 273 if let Some(else_branch) = else_branch {
@@ -457,11 +445,7 @@ impl Pat {
457 args.iter().map(|pat| *pat).for_each(f); 445 args.iter().map(|pat| *pat).for_each(f);
458 } 446 }
459 Pat::Ref { pat, .. } => f(*pat), 447 Pat::Ref { pat, .. } => f(*pat),
460 Pat::Slice { 448 Pat::Slice { prefix, rest, suffix } => {
461 prefix,
462 rest,
463 suffix,
464 } => {
465 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); 449 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
466 total_iter.map(|pat| *pat).for_each(f); 450 total_iter.map(|pat| *pat).for_each(f);
467 } 451 }
@@ -520,10 +504,7 @@ impl ExprCollector {
520 } 504 }
521 505
522 fn empty_block(&mut self) -> ExprId { 506 fn empty_block(&mut self) -> ExprId {
523 let block = Expr::Block { 507 let block = Expr::Block { statements: Vec::new(), tail: None };
524 statements: Vec::new(),
525 tail: None,
526 };
527 self.exprs.alloc(block) 508 self.exprs.alloc(block)
528 } 509 }
529 510
@@ -549,24 +530,10 @@ impl ExprCollector {
549 .unwrap_or_else(|| self.empty_block()); 530 .unwrap_or_else(|| self.empty_block());
550 let placeholder_pat = self.pats.alloc(Pat::Missing); 531 let placeholder_pat = self.pats.alloc(Pat::Missing);
551 let arms = vec![ 532 let arms = vec![
552 MatchArm { 533 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
553 pats: vec![pat], 534 MatchArm { pats: vec![placeholder_pat], expr: else_branch, guard: None },
554 expr: then_branch,
555 guard: None,
556 },
557 MatchArm {
558 pats: vec![placeholder_pat],
559 expr: else_branch,
560 guard: None,
561 },
562 ]; 535 ];
563 self.alloc_expr( 536 self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr)
564 Expr::Match {
565 expr: match_expr,
566 arms,
567 },
568 syntax_ptr,
569 )
570 } else { 537 } else {
571 let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); 538 let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr()));
572 let then_branch = self.collect_block_opt(e.then_branch()); 539 let then_branch = self.collect_block_opt(e.then_branch());
@@ -577,14 +544,7 @@ impl ExprCollector {
577 self.collect_expr(expr) 544 self.collect_expr(expr)
578 } 545 }
579 }); 546 });
580 self.alloc_expr( 547 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
581 Expr::If {
582 condition,
583 then_branch,
584 else_branch,
585 },
586 syntax_ptr,
587 )
588 } 548 }
589 } 549 }
590 ast::ExprKind::BlockExpr(e) => self.collect_block_opt(e.block()), 550 ast::ExprKind::BlockExpr(e) => self.collect_block_opt(e.block()),
@@ -610,14 +570,7 @@ impl ExprCollector {
610 let iterable = self.collect_expr_opt(e.iterable()); 570 let iterable = self.collect_expr_opt(e.iterable());
611 let pat = self.collect_pat_opt(e.pat()); 571 let pat = self.collect_pat_opt(e.pat());
612 let body = self.collect_block_opt(e.loop_body()); 572 let body = self.collect_block_opt(e.loop_body());
613 self.alloc_expr( 573 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr)
614 Expr::For {
615 iterable,
616 pat,
617 body,
618 },
619 syntax_ptr,
620 )
621 } 574 }
622 ast::ExprKind::CallExpr(e) => { 575 ast::ExprKind::CallExpr(e) => {
623 let callee = self.collect_expr_opt(e.expr()); 576 let callee = self.collect_expr_opt(e.expr());
@@ -635,18 +588,8 @@ impl ExprCollector {
635 } else { 588 } else {
636 Vec::new() 589 Vec::new()
637 }; 590 };
638 let method_name = e 591 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
639 .name_ref() 592 self.alloc_expr(Expr::MethodCall { receiver, method_name, args }, syntax_ptr)
640 .map(|nr| nr.as_name())
641 .unwrap_or_else(Name::missing);
642 self.alloc_expr(
643 Expr::MethodCall {
644 receiver,
645 method_name,
646 args,
647 },
648 syntax_ptr,
649 )
650 } 593 }
651 ast::ExprKind::MatchExpr(e) => { 594 ast::ExprKind::MatchExpr(e) => {
652 let expr = self.collect_expr_opt(e.expr()); 595 let expr = self.collect_expr_opt(e.expr());
@@ -668,11 +611,8 @@ impl ExprCollector {
668 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) 611 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
669 } 612 }
670 ast::ExprKind::PathExpr(e) => { 613 ast::ExprKind::PathExpr(e) => {
671 let path = e 614 let path =
672 .path() 615 e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing);
673 .and_then(Path::from_ast)
674 .map(Expr::Path)
675 .unwrap_or(Expr::Missing);
676 self.alloc_expr(path, syntax_ptr) 616 self.alloc_expr(path, syntax_ptr)
677 } 617 }
678 ast::ExprKind::ContinueExpr(_e) => { 618 ast::ExprKind::ContinueExpr(_e) => {
@@ -721,21 +661,11 @@ impl ExprCollector {
721 Vec::new() 661 Vec::new()
722 }; 662 };
723 let spread = e.spread().map(|s| self.collect_expr(s)); 663 let spread = e.spread().map(|s| self.collect_expr(s));
724 self.alloc_expr( 664 self.alloc_expr(Expr::StructLit { path, fields, spread }, syntax_ptr)
725 Expr::StructLit {
726 path,
727 fields,
728 spread,
729 },
730 syntax_ptr,
731 )
732 } 665 }
733 ast::ExprKind::FieldExpr(e) => { 666 ast::ExprKind::FieldExpr(e) => {
734 let expr = self.collect_expr_opt(e.expr()); 667 let expr = self.collect_expr_opt(e.expr());
735 let name = e 668 let name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
736 .name_ref()
737 .map(|nr| nr.as_name())
738 .unwrap_or_else(Name::missing);
739 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr) 669 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
740 } 670 }
741 ast::ExprKind::TryExpr(e) => { 671 ast::ExprKind::TryExpr(e) => {
@@ -772,14 +702,7 @@ impl ExprCollector {
772 } 702 }
773 } 703 }
774 let body = self.collect_expr_opt(e.body()); 704 let body = self.collect_expr_opt(e.body());
775 self.alloc_expr( 705 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
776 Expr::Lambda {
777 args,
778 arg_types,
779 body,
780 },
781 syntax_ptr,
782 )
783 } 706 }
784 ast::ExprKind::BinExpr(e) => { 707 ast::ExprKind::BinExpr(e) => {
785 let lhs = self.collect_expr_opt(e.lhs()); 708 let lhs = self.collect_expr_opt(e.lhs());
@@ -804,9 +727,8 @@ impl ExprCollector {
804 727
805 let lit = match child.flavor() { 728 let lit = match child.flavor() {
806 LiteralFlavor::IntNumber { suffix } => { 729 LiteralFlavor::IntNumber { suffix } => {
807 let known_name = suffix 730 let known_name =
808 .map(Name::new) 731 suffix.map(Name::new).and_then(|name| UncertainIntTy::from_name(&name));
809 .and_then(|name| UncertainIntTy::from_name(&name));
810 732
811 Literal::Int( 733 Literal::Int(
812 Default::default(), 734 Default::default(),
@@ -857,11 +779,7 @@ impl ExprCollector {
857 let pat = self.collect_pat_opt(stmt.pat()); 779 let pat = self.collect_pat_opt(stmt.pat());
858 let type_ref = stmt.type_ref().map(TypeRef::from_ast); 780 let type_ref = stmt.type_ref().map(TypeRef::from_ast);
859 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 781 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
860 Statement::Let { 782 Statement::Let { pat, type_ref, initializer }
861 pat,
862 type_ref,
863 initializer,
864 }
865 } 783 }
866 ast::StmtKind::ExprStmt(stmt) => { 784 ast::StmtKind::ExprStmt(stmt) => {
867 Statement::Expr(self.collect_expr_opt(stmt.expr())) 785 Statement::Expr(self.collect_expr_opt(stmt.expr()))
@@ -869,10 +787,7 @@ impl ExprCollector {
869 }) 787 })
870 .collect(); 788 .collect();
871 let tail = block.expr().map(|e| self.collect_expr(e)); 789 let tail = block.expr().map(|e| self.collect_expr(e));
872 self.alloc_expr( 790 self.alloc_expr(Expr::Block { statements, tail }, SyntaxNodePtr::new(block.syntax()))
873 Expr::Block { statements, tail },
874 SyntaxNodePtr::new(block.syntax()),
875 )
876 } 791 }
877 792
878 fn collect_block_opt(&mut self, block: Option<&ast::Block>) -> ExprId { 793 fn collect_block_opt(&mut self, block: Option<&ast::Block>) -> ExprId {
@@ -886,17 +801,10 @@ impl ExprCollector {
886 fn collect_pat(&mut self, pat: &ast::Pat) -> PatId { 801 fn collect_pat(&mut self, pat: &ast::Pat) -> PatId {
887 let pattern = match pat.kind() { 802 let pattern = match pat.kind() {
888 ast::PatKind::BindPat(bp) => { 803 ast::PatKind::BindPat(bp) => {
889 let name = bp 804 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
890 .name()
891 .map(|nr| nr.as_name())
892 .unwrap_or_else(Name::missing);
893 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref()); 805 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
894 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); 806 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
895 Pat::Bind { 807 Pat::Bind { name, mode: annotation, subpat }
896 name,
897 mode: annotation,
898 subpat,
899 }
900 } 808 }
901 ast::PatKind::TupleStructPat(p) => { 809 ast::PatKind::TupleStructPat(p) => {
902 let path = p.path().and_then(Path::from_ast); 810 let path = p.path().and_then(Path::from_ast);
@@ -919,9 +827,8 @@ impl ExprCollector {
919 ast::PatKind::PlaceholderPat(_) => Pat::Wild, 827 ast::PatKind::PlaceholderPat(_) => Pat::Wild,
920 ast::PatKind::StructPat(p) => { 828 ast::PatKind::StructPat(p) => {
921 let path = p.path().and_then(Path::from_ast); 829 let path = p.path().and_then(Path::from_ast);
922 let field_pat_list = p 830 let field_pat_list =
923 .field_pat_list() 831 p.field_pat_list().expect("every struct should have a field list");
924 .expect("every struct should have a field list");
925 let mut fields: Vec<_> = field_pat_list 832 let mut fields: Vec<_> = field_pat_list
926 .bind_pats() 833 .bind_pats()
927 .map(|bind_pat| { 834 .map(|bind_pat| {
@@ -961,10 +868,7 @@ impl ExprCollector {
961 if let Some(param_list) = node.param_list() { 868 if let Some(param_list) = node.param_list() {
962 if let Some(self_param) = param_list.self_param() { 869 if let Some(self_param) = param_list.self_param() {
963 let self_param = SyntaxNodePtr::new( 870 let self_param = SyntaxNodePtr::new(
964 self_param 871 self_param.self_kw().expect("self param without self keyword").syntax(),
965 .self_kw()
966 .expect("self param without self keyword")
967 .syntax(),
968 ); 872 );
969 let param_pat = self.alloc_pat( 873 let param_pat = self.alloc_pat(
970 Pat::Bind { 874 Pat::Bind {
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 368994bf7..44d5c2429 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -74,17 +74,11 @@ impl ExprScopes {
74 } 74 }
75 75
76 fn root_scope(&mut self) -> ScopeId { 76 fn root_scope(&mut self) -> ScopeId {
77 self.scopes.alloc(ScopeData { 77 self.scopes.alloc(ScopeData { parent: None, entries: vec![] })
78 parent: None,
79 entries: vec![],
80 })
81 } 78 }
82 79
83 fn new_scope(&mut self, parent: ScopeId) -> ScopeId { 80 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
84 self.scopes.alloc(ScopeData { 81 self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] })
85 parent: Some(parent),
86 entries: vec![],
87 })
88 } 82 }
89 83
90 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 84 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
@@ -92,10 +86,7 @@ impl ExprScopes {
92 Pat::Bind { name, .. } => { 86 Pat::Bind { name, .. } => {
93 // bind can have a subpattern, but it's actually not allowed 87 // bind can have a subpattern, but it's actually not allowed
94 // to bind to things in there 88 // to bind to things in there
95 let entry = ScopeEntry { 89 let entry = ScopeEntry { name: name.clone(), pat };
96 name: name.clone(),
97 pat,
98 };
99 self.scopes[scope].entries.push(entry) 90 self.scopes[scope].entries.push(entry)
100 } 91 }
101 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), 92 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)),
@@ -104,9 +95,7 @@ impl ExprScopes {
104 95
105 fn add_params_bindings(&mut self, scope: ScopeId, params: &[PatId]) { 96 fn add_params_bindings(&mut self, scope: ScopeId, params: &[PatId]) {
106 let body = Arc::clone(&self.body); 97 let body = Arc::clone(&self.body);
107 params 98 params.iter().for_each(|pat| self.add_bindings(&body, scope, *pat));
108 .iter()
109 .for_each(|pat| self.add_bindings(&body, scope, *pat));
110 } 99 }
111 100
112 fn set_scope(&mut self, node: ExprId, scope: ScopeId) { 101 fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
@@ -142,9 +131,7 @@ impl ScopeEntryWithSyntax {
142 131
143impl ScopesWithSyntaxMapping { 132impl ScopesWithSyntaxMapping {
144 fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { 133 fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a {
145 generate(self.scope_for(node), move |&scope| { 134 generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent)
146 self.scopes.scopes[scope].parent
147 })
148 } 135 }
149 136
150 pub fn scope_for_offset(&self, offset: TextUnit) -> Option<ScopeId> { 137 pub fn scope_for_offset(&self, offset: TextUnit) -> Option<ScopeId> {
@@ -154,10 +141,7 @@ impl ScopesWithSyntaxMapping {
154 .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) 141 .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope)))
155 // find containing scope 142 // find containing scope
156 .min_by_key(|(ptr, _scope)| { 143 .min_by_key(|(ptr, _scope)| {
157 ( 144 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len())
158 !(ptr.range().start() <= offset && offset <= ptr.range().end()),
159 ptr.range().len(),
160 )
161 }) 145 })
162 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)) 146 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset))
163 } 147 }
@@ -251,9 +235,7 @@ fn compute_block_scopes(
251) { 235) {
252 for stmt in statements { 236 for stmt in statements {
253 match stmt { 237 match stmt {
254 Statement::Let { 238 Statement::Let { pat, initializer, .. } => {
255 pat, initializer, ..
256 } => {
257 if let Some(expr) = initializer { 239 if let Some(expr) = initializer {
258 scopes.set_scope(*expr, scope); 240 scopes.set_scope(*expr, scope);
259 compute_expr_scopes(*expr, body, scopes, scope); 241 compute_expr_scopes(*expr, body, scopes, scope);
@@ -278,21 +260,13 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
278 Expr::Block { statements, tail } => { 260 Expr::Block { statements, tail } => {
279 compute_block_scopes(&statements, *tail, body, scopes, scope); 261 compute_block_scopes(&statements, *tail, body, scopes, scope);
280 } 262 }
281 Expr::For { 263 Expr::For { iterable, pat, body: body_expr } => {
282 iterable,
283 pat,
284 body: body_expr,
285 } => {
286 compute_expr_scopes(*iterable, body, scopes, scope); 264 compute_expr_scopes(*iterable, body, scopes, scope);
287 let scope = scopes.new_scope(scope); 265 let scope = scopes.new_scope(scope);
288 scopes.add_bindings(body, scope, *pat); 266 scopes.add_bindings(body, scope, *pat);
289 compute_expr_scopes(*body_expr, body, scopes, scope); 267 compute_expr_scopes(*body_expr, body, scopes, scope);
290 } 268 }
291 Expr::Lambda { 269 Expr::Lambda { args, body: body_expr, .. } => {
292 args,
293 body: body_expr,
294 ..
295 } => {
296 let scope = scopes.new_scope(scope); 270 let scope = scopes.new_scope(scope);
297 scopes.add_params_bindings(scope, &args); 271 scopes.add_params_bindings(scope, &args);
298 compute_expr_scopes(*body_expr, body, scopes, scope); 272 compute_expr_scopes(*body_expr, body, scopes, scope);
@@ -341,9 +315,7 @@ mod tests {
341 let file = SourceFile::parse(&code); 315 let file = SourceFile::parse(&code);
342 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 316 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
343 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 317 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
344 let irrelevant_function = Function { 318 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
345 id: crate::ids::FunctionId::from_raw(0.into()),
346 };
347 let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def); 319 let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def);
348 let scopes = ExprScopes::new(Arc::clone(body_hir.body())); 320 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
349 let scopes = ScopesWithSyntaxMapping { 321 let scopes = ScopesWithSyntaxMapping {
@@ -444,9 +416,7 @@ mod tests {
444 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 416 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
445 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 417 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
446 418
447 let irrelevant_function = Function { 419 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
448 id: crate::ids::FunctionId::from_raw(0.into()),
449 };
450 let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def); 420 let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def);
451 let scopes = ExprScopes::new(Arc::clone(body_hir.body())); 421 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
452 let scopes = ScopesWithSyntaxMapping { 422 let scopes = ScopesWithSyntaxMapping {
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index a82205f0b..c72360f44 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -58,14 +58,8 @@ impl GenericParams {
58 58
59 fn fill_params(&mut self, params: &ast::TypeParamList) { 59 fn fill_params(&mut self, params: &ast::TypeParamList) {
60 for (idx, type_param) in params.type_params().enumerate() { 60 for (idx, type_param) in params.type_params().enumerate() {
61 let name = type_param 61 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
62 .name() 62 let param = GenericParam { idx: idx as u32, name };
63 .map(AsName::as_name)
64 .unwrap_or_else(Name::missing);
65 let param = GenericParam {
66 idx: idx as u32,
67 name,
68 };
69 self.params.push(param); 63 self.params.push(param);
70 } 64 }
71 } 65 }
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 95678bf70..ea13c1196 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -169,11 +169,7 @@ impl<N: AstNode> Hash for ItemLoc<N> {
169 169
170impl<N: AstNode> Clone for ItemLoc<N> { 170impl<N: AstNode> Clone for ItemLoc<N> {
171 fn clone(&self) -> ItemLoc<N> { 171 fn clone(&self) -> ItemLoc<N> {
172 ItemLoc { 172 ItemLoc { module: self.module, raw: self.raw, _ty: PhantomData }
173 module: self.module,
174 raw: self.raw,
175 _ty: PhantomData,
176 }
177 } 173 }
178} 174}
179 175
@@ -186,11 +182,7 @@ pub(crate) struct LocationCtx<DB> {
186 182
187impl<'a, DB: PersistentHirDatabase> LocationCtx<&'a DB> { 183impl<'a, DB: PersistentHirDatabase> LocationCtx<&'a DB> {
188 pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { 184 pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> {
189 LocationCtx { 185 LocationCtx { db, module, file_id }
190 db,
191 module,
192 file_id,
193 }
194 } 186 }
195 pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF 187 pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF
196 where 188 where
@@ -205,15 +197,9 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
205 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>; 197 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>;
206 fn from_ast(ctx: LocationCtx<&impl PersistentHirDatabase>, ast: &N) -> Self { 198 fn from_ast(ctx: LocationCtx<&impl PersistentHirDatabase>, ast: &N) -> Self {
207 let items = ctx.db.file_items(ctx.file_id); 199 let items = ctx.db.file_items(ctx.file_id);
208 let raw = SourceItemId { 200 let raw =
209 file_id: ctx.file_id, 201 SourceItemId { file_id: ctx.file_id, item_id: items.id_of(ctx.file_id, ast.syntax()) };
210 item_id: items.id_of(ctx.file_id, ast.syntax()), 202 let loc = ItemLoc { module: ctx.module, raw, _ty: PhantomData };
211 };
212 let loc = ItemLoc {
213 module: ctx.module,
214 raw,
215 _ty: PhantomData,
216 };
217 203
218 Self::interner(ctx.db.as_ref()).loc2id(&loc) 204 Self::interner(ctx.db.as_ref()).loc2id(&loc)
219 } 205 }
@@ -221,9 +207,8 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
221 let int = Self::interner(db.as_ref()); 207 let int = Self::interner(db.as_ref());
222 let loc = int.id2loc(self); 208 let loc = int.id2loc(self);
223 let syntax = db.file_item(loc.raw); 209 let syntax = db.file_item(loc.raw);
224 let ast = N::cast(&syntax) 210 let ast =
225 .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)) 211 N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned();
226 .to_owned();
227 (loc.raw.file_id, ast) 212 (loc.raw.file_id, ast)
228 } 213 }
229 fn module(self, db: &impl HirDatabase) -> Module { 214 fn module(self, db: &impl HirDatabase) -> Module {
@@ -317,10 +302,7 @@ pub struct SourceFileItems {
317 302
318impl SourceFileItems { 303impl SourceFileItems {
319 pub(crate) fn new(file_id: HirFileId, source_file: &SourceFile) -> SourceFileItems { 304 pub(crate) fn new(file_id: HirFileId, source_file: &SourceFile) -> SourceFileItems {
320 let mut res = SourceFileItems { 305 let mut res = SourceFileItems { file_id, arena: Arena::default() };
321 file_id,
322 arena: Arena::default(),
323 };
324 res.init(source_file); 306 res.init(source_file);
325 res 307 res
326 } 308 }
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 094dbedb3..b2fbee8d7 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -50,17 +50,11 @@ impl ImplBlock {
50 item: ImplItem, 50 item: ImplItem,
51 ) -> Option<ImplBlock> { 51 ) -> Option<ImplBlock> {
52 let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; 52 let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
53 Some(ImplBlock { 53 Some(ImplBlock { module_impl_blocks, impl_id })
54 module_impl_blocks,
55 impl_id,
56 })
57 } 54 }
58 55
59 pub(crate) fn from_id(module_impl_blocks: Arc<ModuleImplBlocks>, impl_id: ImplId) -> ImplBlock { 56 pub(crate) fn from_id(module_impl_blocks: Arc<ModuleImplBlocks>, impl_id: ImplId) -> ImplBlock {
60 ImplBlock { 57 ImplBlock { module_impl_blocks, impl_id }
61 module_impl_blocks,
62 impl_id,
63 }
64 } 58 }
65 59
66 pub fn id(&self) -> ImplId { 60 pub fn id(&self) -> ImplId {
@@ -144,11 +138,7 @@ impl ImplData {
144 } else { 138 } else {
145 Vec::new() 139 Vec::new()
146 }; 140 };
147 ImplData { 141 ImplData { target_trait, target_type, items }
148 target_trait,
149 target_type,
150 items,
151 }
152 } 142 }
153 143
154 pub fn target_trait(&self) -> Option<&TypeRef> { 144 pub fn target_trait(&self) -> Option<&TypeRef> {
@@ -212,10 +202,9 @@ impl ModuleImplBlocks {
212 let file_id: HirFileId = file_id.into(); 202 let file_id: HirFileId = file_id.into();
213 let node = match &module_source { 203 let node = match &module_source {
214 ModuleSource::SourceFile(node) => node.syntax(), 204 ModuleSource::SourceFile(node) => node.syntax(),
215 ModuleSource::Module(node) => node 205 ModuleSource::Module(node) => {
216 .item_list() 206 node.item_list().expect("inline module should have item list").syntax()
217 .expect("inline module should have item list") 207 }
218 .syntax(),
219 }; 208 };
220 209
221 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { 210 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index cb8a9312e..95925159f 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -48,9 +48,7 @@ impl MacroDef {
48 48
49 let input = { 49 let input = {
50 let arg = macro_call.token_tree()?.syntax(); 50 let arg = macro_call.token_tree()?.syntax();
51 MacroInput { 51 MacroInput { text: arg.text().to_string() }
52 text: arg.text().to_string(),
53 }
54 }; 52 };
55 Some((def, input)) 53 Some((def, input))
56 } 54 }
@@ -68,20 +66,14 @@ impl MacroDef {
68 let ptr = SyntaxNodePtr::new(array_expr.syntax()); 66 let ptr = SyntaxNodePtr::new(array_expr.syntax());
69 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); 67 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
70 let ranges_map = vec![(src_range, array_expr.syntax().range())]; 68 let ranges_map = vec![(src_range, array_expr.syntax().range())];
71 let res = MacroExpansion { 69 let res = MacroExpansion { text, ranges_map, ptr };
72 text,
73 ranges_map,
74 ptr,
75 };
76 Some(res) 70 Some(res)
77 } 71 }
78 fn expand_query_group(self, input: MacroInput) -> Option<MacroExpansion> { 72 fn expand_query_group(self, input: MacroInput) -> Option<MacroExpansion> {
79 let anchor = "trait "; 73 let anchor = "trait ";
80 let pos = input.text.find(anchor)? + anchor.len(); 74 let pos = input.text.find(anchor)? + anchor.len();
81 let trait_name = input.text[pos..] 75 let trait_name =
82 .chars() 76 input.text[pos..].chars().take_while(|c| c.is_alphabetic()).collect::<String>();
83 .take_while(|c| c.is_alphabetic())
84 .collect::<String>();
85 if trait_name.is_empty() { 77 if trait_name.is_empty() {
86 return None; 78 return None;
87 } 79 }
@@ -92,11 +84,7 @@ impl MacroDef {
92 let name = trait_def.name()?; 84 let name = trait_def.name()?;
93 let ptr = SyntaxNodePtr::new(trait_def.syntax()); 85 let ptr = SyntaxNodePtr::new(trait_def.syntax());
94 let ranges_map = vec![(src_range, name.syntax().range())]; 86 let ranges_map = vec![(src_range, name.syntax().range())];
95 let res = MacroExpansion { 87 let res = MacroExpansion { text, ranges_map, ptr };
96 text,
97 ranges_map,
98 ptr,
99 };
100 Some(res) 88 Some(res)
101 } 89 }
102} 90}
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 87095fb21..950f89948 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -64,10 +64,7 @@ impl MockDatabase {
64 let mut source_root = SourceRoot::default(); 64 let mut source_root = SourceRoot::default();
65 for entry in parse_fixture(fixture) { 65 for entry in parse_fixture(fixture) {
66 if entry.text.contains(CURSOR_MARKER) { 66 if entry.text.contains(CURSOR_MARKER) {
67 assert!( 67 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
68 position.is_none(),
69 "only one marker (<|>) per fixture is allowed"
70 );
71 position = Some(self.add_file_with_position( 68 position = Some(self.add_file_with_position(
72 source_root_id, 69 source_root_id,
73 &mut source_root, 70 &mut source_root,
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index a1aa3d8ce..1f19ee191 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -153,10 +153,8 @@ impl ModuleTree {
153 file_id: HirFileId, 153 file_id: HirFileId,
154 decl_id: Option<SourceFileItemId>, 154 decl_id: Option<SourceFileItemId>,
155 ) -> Option<ModuleId> { 155 ) -> Option<ModuleId> {
156 let (res, _) = self 156 let (res, _) =
157 .mods 157 self.mods.iter().find(|(_, m)| (m.file_id, m.decl_id) == (file_id, decl_id))?;
158 .iter()
159 .find(|(_, m)| (m.file_id, m.decl_id) == (file_id, decl_id))?;
160 Some(res) 158 Some(res)
161 } 159 }
162 160
@@ -178,18 +176,10 @@ impl ModuleTree {
178 decl_id: Option<SourceFileItemId>, 176 decl_id: Option<SourceFileItemId>,
179 ) -> ModuleId { 177 ) -> ModuleId {
180 let is_root = parent.is_none(); 178 let is_root = parent.is_none();
181 let id = self.alloc_mod(ModuleData { 179 let id = self.alloc_mod(ModuleData { file_id, decl_id, parent, children: Vec::new() });
182 file_id,
183 decl_id,
184 parent,
185 children: Vec::new(),
186 });
187 for sub in db.submodules(file_id, decl_id).iter() { 180 for sub in db.submodules(file_id, decl_id).iter() {
188 let link = self.alloc_link(LinkData { 181 let link = self.alloc_link(LinkData {
189 source: SourceItemId { 182 source: SourceItemId { file_id, item_id: sub.decl_id },
190 file_id,
191 item_id: sub.decl_id,
192 },
193 name: sub.name.clone(), 183 name: sub.name.clone(),
194 owner: id, 184 owner: id,
195 points_to: Vec::new(), 185 points_to: Vec::new(),
@@ -244,9 +234,7 @@ impl ModuleId {
244 Some(tree.links[link].owner) 234 Some(tree.links[link].owner)
245 } 235 }
246 pub(crate) fn crate_root(self, tree: &ModuleTree) -> ModuleId { 236 pub(crate) fn crate_root(self, tree: &ModuleTree) -> ModuleId {
247 generate(Some(self), move |it| it.parent(tree)) 237 generate(Some(self), move |it| it.parent(tree)).last().unwrap()
248 .last()
249 .unwrap()
250 } 238 }
251 pub(crate) fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> { 239 pub(crate) fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> {
252 let link = tree.mods[self] 240 let link = tree.mods[self]
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 681aa9a67..b7382d9c3 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -83,40 +83,25 @@ pub struct PerNs<T> {
83 83
84impl<T> Default for PerNs<T> { 84impl<T> Default for PerNs<T> {
85 fn default() -> Self { 85 fn default() -> Self {
86 PerNs { 86 PerNs { types: None, values: None }
87 types: None,
88 values: None,
89 }
90 } 87 }
91} 88}
92 89
93impl<T> PerNs<T> { 90impl<T> PerNs<T> {
94 pub fn none() -> PerNs<T> { 91 pub fn none() -> PerNs<T> {
95 PerNs { 92 PerNs { types: None, values: None }
96 types: None,
97 values: None,
98 }
99 } 93 }
100 94
101 pub fn values(t: T) -> PerNs<T> { 95 pub fn values(t: T) -> PerNs<T> {
102 PerNs { 96 PerNs { types: None, values: Some(t) }
103 types: None,
104 values: Some(t),
105 }
106 } 97 }
107 98
108 pub fn types(t: T) -> PerNs<T> { 99 pub fn types(t: T) -> PerNs<T> {
109 PerNs { 100 PerNs { types: Some(t), values: None }
110 types: Some(t),
111 values: None,
112 }
113 } 101 }
114 102
115 pub fn both(types: T, values: T) -> PerNs<T> { 103 pub fn both(types: T, values: T) -> PerNs<T> {
116 PerNs { 104 PerNs { types: Some(types), values: Some(values) }
117 types: Some(types),
118 values: Some(values),
119 }
120 } 105 }
121 106
122 pub fn is_none(&self) -> bool { 107 pub fn is_none(&self) -> bool {
@@ -147,31 +132,19 @@ impl<T> PerNs<T> {
147 } 132 }
148 133
149 pub fn as_ref(&self) -> PerNs<&T> { 134 pub fn as_ref(&self) -> PerNs<&T> {
150 PerNs { 135 PerNs { types: self.types.as_ref(), values: self.values.as_ref() }
151 types: self.types.as_ref(),
152 values: self.values.as_ref(),
153 }
154 } 136 }
155 137
156 pub fn combine(self, other: PerNs<T>) -> PerNs<T> { 138 pub fn combine(self, other: PerNs<T>) -> PerNs<T> {
157 PerNs { 139 PerNs { types: self.types.or(other.types), values: self.values.or(other.values) }
158 types: self.types.or(other.types),
159 values: self.values.or(other.values),
160 }
161 } 140 }
162 141
163 pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { 142 pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> {
164 PerNs { 143 PerNs { types: self.types.and_then(&f), values: self.values.and_then(&f) }
165 types: self.types.and_then(&f),
166 values: self.values.and_then(&f),
167 }
168 } 144 }
169 145
170 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> { 146 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> {
171 PerNs { 147 PerNs { types: self.types.map(&f), values: self.values.map(&f) }
172 types: self.types.map(&f),
173 values: self.values.map(&f),
174 }
175 } 148 }
176} 149}
177 150
@@ -233,9 +206,7 @@ where
233 for dep in self.krate.dependencies(self.db) { 206 for dep in self.krate.dependencies(self.db) {
234 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); 207 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
235 if let Some(module) = dep.krate.root_module(self.db) { 208 if let Some(module) = dep.krate.root_module(self.db) {
236 self.result 209 self.result.extern_prelude.insert(dep.name.clone(), module.into());
237 .extern_prelude
238 .insert(dep.name.clone(), module.into());
239 } 210 }
240 } 211 }
241 } 212 }
@@ -245,17 +216,11 @@ where
245 for (import_id, import_data) in input.imports.iter() { 216 for (import_id, import_data) in input.imports.iter() {
246 if let Some(last_segment) = import_data.path.segments.iter().last() { 217 if let Some(last_segment) = import_data.path.segments.iter().last() {
247 if !import_data.is_glob { 218 if !import_data.is_glob {
248 let name = import_data 219 let name =
249 .alias 220 import_data.alias.clone().unwrap_or_else(|| last_segment.name.clone());
250 .clone() 221 module_items
251 .unwrap_or_else(|| last_segment.name.clone()); 222 .items
252 module_items.items.insert( 223 .insert(name, Resolution { def: PerNs::none(), import: Some(import_id) });
253 name,
254 Resolution {
255 def: PerNs::none(),
256 import: Some(import_id),
257 },
258 );
259 } 224 }
260 } 225 }
261 } 226 }
@@ -267,10 +232,7 @@ where
267 232
268 // Populate modules 233 // Populate modules
269 for (name, module_id) in module_id.children(&self.module_tree) { 234 for (name, module_id) in module_id.children(&self.module_tree) {
270 let module = Module { 235 let module = Module { module_id, krate: self.krate };
271 module_id,
272 krate: self.krate,
273 };
274 self.add_module_item(&mut module_items, name, PerNs::types(module.into())); 236 self.add_module_item(&mut module_items, name, PerNs::types(module.into()));
275 } 237 }
276 238
@@ -305,20 +267,13 @@ where
305 if import.is_glob { 267 if import.is_glob {
306 return ReachedFixedPoint::Yes; 268 return ReachedFixedPoint::Yes;
307 }; 269 };
308 let original_module = Module { 270 let original_module = Module { krate: self.krate, module_id };
309 krate: self.krate,
310 module_id,
311 };
312 let (def, reached_fixedpoint) = 271 let (def, reached_fixedpoint) =
313 self.result 272 self.result.resolve_path_fp(self.db, original_module, &import.path);
314 .resolve_path_fp(self.db, original_module, &import.path);
315 273
316 if reached_fixedpoint == ReachedFixedPoint::Yes { 274 if reached_fixedpoint == ReachedFixedPoint::Yes {
317 let last_segment = import.path.segments.last().unwrap(); 275 let last_segment = import.path.segments.last().unwrap();
318 let name = import 276 let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone());
319 .alias
320 .clone()
321 .unwrap_or_else(|| last_segment.name.clone());
322 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); 277 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
323 278
324 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 279 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
@@ -330,10 +285,7 @@ where
330 } 285 }
331 } 286 }
332 self.update(module_id, |items| { 287 self.update(module_id, |items| {
333 let res = Resolution { 288 let res = Resolution { def, import: Some(import_id) };
334 def,
335 import: Some(import_id),
336 };
337 items.items.insert(name, res); 289 items.items.insert(name, res);
338 }); 290 });
339 } 291 }
@@ -358,12 +310,7 @@ impl ItemMap {
358 let module_tree = db.module_tree(krate); 310 let module_tree = db.module_tree(krate);
359 let input = module_tree 311 let input = module_tree
360 .modules() 312 .modules()
361 .map(|module_id| { 313 .map(|module_id| (module_id, db.lower_module_module(Module { krate, module_id })))
362 (
363 module_id,
364 db.lower_module_module(Module { krate, module_id }),
365 )
366 })
367 .collect::<FxHashMap<_, _>>(); 314 .collect::<FxHashMap<_, _>>();
368 315
369 let resolver = Resolver::new(db, &input, krate); 316 let resolver = Resolver::new(db, &input, krate);
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 7e6e48ae0..7e9a3de2b 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -82,13 +82,9 @@ impl LoweredModule {
82 let mut source_map = ImportSourceMap::default(); 82 let mut source_map = ImportSourceMap::default();
83 let mut res = LoweredModule::default(); 83 let mut res = LoweredModule::default();
84 match source { 84 match source {
85 ModuleSource::SourceFile(it) => res.fill( 85 ModuleSource::SourceFile(it) => {
86 &mut source_map, 86 res.fill(&mut source_map, db, module, file_id, &mut it.items_with_macros())
87 db, 87 }
88 module,
89 file_id,
90 &mut it.items_with_macros(),
91 ),
92 ModuleSource::Module(it) => { 88 ModuleSource::Module(it) => {
93 if let Some(item_list) = it.item_list() { 89 if let Some(item_list) = it.item_list() {
94 res.fill( 90 res.fill(
@@ -121,10 +117,8 @@ impl LoweredModule {
121 } 117 }
122 ast::ItemOrMacro::Macro(macro_call) => { 118 ast::ItemOrMacro::Macro(macro_call) => {
123 let item_id = file_items.id_of_unchecked(macro_call.syntax()); 119 let item_id = file_items.id_of_unchecked(macro_call.syntax());
124 let loc = MacroCallLoc { 120 let loc =
125 module, 121 MacroCallLoc { module, source_item_id: SourceItemId { file_id, item_id } };
126 source_item_id: SourceItemId { file_id, item_id },
127 };
128 let id = loc.id(db); 122 let id = loc.id(db);
129 let file_id = HirFileId::from(id); 123 let file_id = HirFileId::from(id);
130 //FIXME: expand recursively 124 //FIXME: expand recursively
@@ -163,22 +157,19 @@ impl LoweredModule {
163 ast::ModuleItemKind::FnDef(it) => { 157 ast::ModuleItemKind::FnDef(it) => {
164 if let Some(name) = it.name() { 158 if let Some(name) = it.name() {
165 let func = Function { id: ctx.to_def(it) }; 159 let func = Function { id: ctx.to_def(it) };
166 self.declarations 160 self.declarations.insert(name.as_name(), PerNs::values(func.into()));
167 .insert(name.as_name(), PerNs::values(func.into()));
168 } 161 }
169 } 162 }
170 ast::ModuleItemKind::TraitDef(it) => { 163 ast::ModuleItemKind::TraitDef(it) => {
171 if let Some(name) = it.name() { 164 if let Some(name) = it.name() {
172 let t = Trait { id: ctx.to_def(it) }; 165 let t = Trait { id: ctx.to_def(it) };
173 self.declarations 166 self.declarations.insert(name.as_name(), PerNs::types(t.into()));
174 .insert(name.as_name(), PerNs::types(t.into()));
175 } 167 }
176 } 168 }
177 ast::ModuleItemKind::TypeDef(it) => { 169 ast::ModuleItemKind::TypeDef(it) => {
178 if let Some(name) = it.name() { 170 if let Some(name) = it.name() {
179 let t = Type { id: ctx.to_def(it) }; 171 let t = Type { id: ctx.to_def(it) };
180 self.declarations 172 self.declarations.insert(name.as_name(), PerNs::types(t.into()));
181 .insert(name.as_name(), PerNs::types(t.into()));
182 } 173 }
183 } 174 }
184 ast::ModuleItemKind::ImplBlock(_) => { 175 ast::ModuleItemKind::ImplBlock(_) => {
@@ -207,15 +198,13 @@ impl LoweredModule {
207 ast::ModuleItemKind::ConstDef(it) => { 198 ast::ModuleItemKind::ConstDef(it) => {
208 if let Some(name) = it.name() { 199 if let Some(name) = it.name() {
209 let c = Const { id: ctx.to_def(it) }; 200 let c = Const { id: ctx.to_def(it) };
210 self.declarations 201 self.declarations.insert(name.as_name(), PerNs::values(c.into()));
211 .insert(name.as_name(), PerNs::values(c.into()));
212 } 202 }
213 } 203 }
214 ast::ModuleItemKind::StaticDef(it) => { 204 ast::ModuleItemKind::StaticDef(it) => {
215 if let Some(name) = it.name() { 205 if let Some(name) = it.name() {
216 let s = Static { id: ctx.to_def(it) }; 206 let s = Static { id: ctx.to_def(it) };
217 self.declarations 207 self.declarations.insert(name.as_name(), PerNs::values(s.into()));
218 .insert(name.as_name(), PerNs::values(s.into()));
219 } 208 }
220 } 209 }
221 ast::ModuleItemKind::Module(_) => { 210 ast::ModuleItemKind::Module(_) => {
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 0654dbaa1..3dfad6bf2 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -42,19 +42,11 @@ fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
42 .collect::<Vec<_>>(); 42 .collect::<Vec<_>>();
43 lines.sort(); 43 lines.sort();
44 let actual = lines.join("\n"); 44 let actual = lines.join("\n");
45 let expected = expected 45 let expected = expected.trim().lines().map(|it| it.trim()).collect::<Vec<_>>().join("\n");
46 .trim()
47 .lines()
48 .map(|it| it.trim())
49 .collect::<Vec<_>>()
50 .join("\n");
51 assert_eq_text!(&expected, &actual); 46 assert_eq_text!(&expected, &actual);
52 47
53 fn dump_resolution(resolution: &Resolution) -> &'static str { 48 fn dump_resolution(resolution: &Resolution) -> &'static str {
54 match ( 49 match (resolution.def.types.is_some(), resolution.def.values.is_some()) {
55 resolution.def.types.is_some(),
56 resolution.def.values.is_some(),
57 ) {
58 (true, true) => "t v", 50 (true, true) => "t v",
59 (true, false) => "t", 51 (true, false) => "t",
60 (false, true) => "v", 52 (false, true) => "v",
@@ -314,9 +306,7 @@ fn item_map_across_crates() {
314 let mut crate_graph = CrateGraph::default(); 306 let mut crate_graph = CrateGraph::default();
315 let main_crate = crate_graph.add_crate_root(main_id); 307 let main_crate = crate_graph.add_crate_root(main_id);
316 let lib_crate = crate_graph.add_crate_root(lib_id); 308 let lib_crate = crate_graph.add_crate_root(lib_id);
317 crate_graph 309 crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate).unwrap();
318 .add_dep(main_crate, "test_crate".into(), lib_crate)
319 .unwrap();
320 310
321 db.set_crate_graph(Arc::new(crate_graph)); 311 db.set_crate_graph(Arc::new(crate_graph));
322 312
@@ -357,9 +347,7 @@ fn extern_crate_rename() {
357 let mut crate_graph = CrateGraph::default(); 347 let mut crate_graph = CrateGraph::default();
358 let main_crate = crate_graph.add_crate_root(main_id); 348 let main_crate = crate_graph.add_crate_root(main_id);
359 let lib_crate = crate_graph.add_crate_root(lib_id); 349 let lib_crate = crate_graph.add_crate_root(lib_id);
360 crate_graph 350 crate_graph.add_dep(main_crate, "alloc".into(), lib_crate).unwrap();
361 .add_dep(main_crate, "alloc".into(), lib_crate)
362 .unwrap();
363 351
364 db.set_crate_graph(Arc::new(crate_graph)); 352 db.set_crate_graph(Arc::new(crate_graph));
365 353
@@ -406,9 +394,7 @@ fn import_across_source_roots() {
406 let mut crate_graph = CrateGraph::default(); 394 let mut crate_graph = CrateGraph::default();
407 let main_crate = crate_graph.add_crate_root(main_id); 395 let main_crate = crate_graph.add_crate_root(main_id);
408 let lib_crate = crate_graph.add_crate_root(lib_id); 396 let lib_crate = crate_graph.add_crate_root(lib_id);
409 crate_graph 397 crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate).unwrap();
410 .add_dep(main_crate, "test_crate".into(), lib_crate)
411 .unwrap();
412 398
413 db.set_crate_graph(Arc::new(crate_graph)); 399 db.set_crate_graph(Arc::new(crate_graph));
414 400
@@ -447,9 +433,7 @@ fn reexport_across_crates() {
447 let mut crate_graph = CrateGraph::default(); 433 let mut crate_graph = CrateGraph::default();
448 let main_crate = crate_graph.add_crate_root(main_id); 434 let main_crate = crate_graph.add_crate_root(main_id);
449 let lib_crate = crate_graph.add_crate_root(lib_id); 435 let lib_crate = crate_graph.add_crate_root(lib_id);
450 crate_graph 436 crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate).unwrap();
451 .add_dep(main_crate, "test_crate".into(), lib_crate)
452 .unwrap();
453 437
454 db.set_crate_graph(Arc::new(crate_graph)); 438 db.set_crate_graph(Arc::new(crate_graph));
455 439
@@ -482,11 +466,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
482 let events = db.log_executed(|| { 466 let events = db.log_executed(|| {
483 db.item_map(krate); 467 db.item_map(krate);
484 }); 468 });
485 assert!( 469 assert!(!format!("{:?}", events).contains("item_map"), "{:#?}", events)
486 !format!("{:?}", events).contains("item_map"),
487 "{:#?}",
488 events
489 )
490 } 470 }
491} 471}
492 472
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index cb0a04500..6a24c8aa7 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -66,14 +66,9 @@ impl Path {
66 66
67 match segment.kind()? { 67 match segment.kind()? {
68 ast::PathSegmentKind::Name(name) => { 68 ast::PathSegmentKind::Name(name) => {
69 let args = segment 69 let args =
70 .type_arg_list() 70 segment.type_arg_list().and_then(GenericArgs::from_ast).map(Arc::new);
71 .and_then(GenericArgs::from_ast) 71 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
72 .map(Arc::new);
73 let segment = PathSegment {
74 name: name.as_name(),
75 args_and_bindings: args,
76 };
77 segments.push(segment); 72 segments.push(segment);
78 } 73 }
79 ast::PathSegmentKind::CrateKw => { 74 ast::PathSegmentKind::CrateKw => {
@@ -153,10 +148,7 @@ impl From<Name> for Path {
153 fn from(name: Name) -> Path { 148 fn from(name: Name) -> Path {
154 Path { 149 Path {
155 kind: PathKind::Plain, 150 kind: PathKind::Plain,
156 segments: vec![PathSegment { 151 segments: vec![PathSegment { name, args_and_bindings: None }],
157 name,
158 args_and_bindings: None,
159 }],
160 } 152 }
161 } 153 }
162} 154}
@@ -209,18 +201,13 @@ fn expand_use_tree<'a>(
209} 201}
210 202
211fn convert_path(prefix: Option<Path>, path: &ast::Path) -> Option<Path> { 203fn convert_path(prefix: Option<Path>, path: &ast::Path) -> Option<Path> {
212 let prefix = if let Some(qual) = path.qualifier() { 204 let prefix =
213 Some(convert_path(prefix, qual)?) 205 if let Some(qual) = path.qualifier() { Some(convert_path(prefix, qual)?) } else { prefix };
214 } else {
215 prefix
216 };
217 let segment = path.segment()?; 206 let segment = path.segment()?;
218 let res = match segment.kind()? { 207 let res = match segment.kind()? {
219 ast::PathSegmentKind::Name(name) => { 208 ast::PathSegmentKind::Name(name) => {
220 let mut res = prefix.unwrap_or_else(|| Path { 209 let mut res = prefix
221 kind: PathKind::Plain, 210 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
222 segments: Vec::with_capacity(1),
223 });
224 res.segments.push(PathSegment { 211 res.segments.push(PathSegment {
225 name: name.as_name(), 212 name: name.as_name(),
226 args_and_bindings: None, // no type args in use 213 args_and_bindings: None, // no type args in use
@@ -231,28 +218,19 @@ fn convert_path(prefix: Option<Path>, path: &ast::Path) -> Option<Path> {
231 if prefix.is_some() { 218 if prefix.is_some() {
232 return None; 219 return None;
233 } 220 }
234 Path { 221 Path { kind: PathKind::Crate, segments: Vec::new() }
235 kind: PathKind::Crate,
236 segments: Vec::new(),
237 }
238 } 222 }
239 ast::PathSegmentKind::SelfKw => { 223 ast::PathSegmentKind::SelfKw => {
240 if prefix.is_some() { 224 if prefix.is_some() {
241 return None; 225 return None;
242 } 226 }
243 Path { 227 Path { kind: PathKind::Self_, segments: Vec::new() }
244 kind: PathKind::Self_,
245 segments: Vec::new(),
246 }
247 } 228 }
248 ast::PathSegmentKind::SuperKw => { 229 ast::PathSegmentKind::SuperKw => {
249 if prefix.is_some() { 230 if prefix.is_some() {
250 return None; 231 return None;
251 } 232 }
252 Path { 233 Path { kind: PathKind::Super, segments: Vec::new() }
253 kind: PathKind::Super,
254 segments: Vec::new(),
255 }
256 } 234 }
257 }; 235 };
258 Some(res) 236 Some(res)
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index b4d8da1e6..03113e7cc 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -23,7 +23,5 @@ pub(super) fn file_item(
23 source_item_id: SourceItemId, 23 source_item_id: SourceItemId,
24) -> TreeArc<SyntaxNode> { 24) -> TreeArc<SyntaxNode> {
25 let source_file = db.hir_parse(source_item_id.file_id); 25 let source_file = db.hir_parse(source_item_id.file_id);
26 db.file_items(source_item_id.file_id)[source_item_id.item_id] 26 db.file_items(source_item_id.file_id)[source_item_id.item_id].to_node(&source_file).to_owned()
27 .to_node(&source_file)
28 .to_owned()
29} 27}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 0f60d4742..3d7ec5683 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -138,10 +138,7 @@ impl Resolver {
138 expr_scopes: Arc<ExprScopes>, 138 expr_scopes: Arc<ExprScopes>,
139 scope_id: ScopeId, 139 scope_id: ScopeId,
140 ) -> Resolver { 140 ) -> Resolver {
141 self.push_scope(Scope::ExprScope(ExprScope { 141 self.push_scope(Scope::ExprScope(ExprScope { expr_scopes, scope_id }))
142 expr_scopes,
143 scope_id,
144 }))
145 } 142 }
146} 143}
147 144
@@ -170,11 +167,8 @@ impl Scope {
170 } 167 }
171 } 168 }
172 Scope::ExprScope(e) => { 169 Scope::ExprScope(e) => {
173 let entry = e 170 let entry =
174 .expr_scopes 171 e.expr_scopes.entries(e.scope_id).iter().find(|entry| entry.name() == name);
175 .entries(e.scope_id)
176 .iter()
177 .find(|entry| entry.name() == name);
178 match entry { 172 match entry {
179 Some(e) => PerNs::values(Resolution::LocalBinding(e.pat())), 173 Some(e) => PerNs::values(Resolution::LocalBinding(e.pat())),
180 None => PerNs::none(), 174 None => PerNs::none(),
@@ -193,35 +187,24 @@ impl Scope {
193 // def: m.module.into(), 187 // def: m.module.into(),
194 // }), 188 // }),
195 // ); 189 // );
196 m.item_map[m.module.module_id] 190 m.item_map[m.module.module_id].entries().for_each(|(name, res)| {
197 .entries() 191 f(name.clone(), res.def.map(Resolution::Def));
198 .for_each(|(name, res)| { 192 });
199 f(name.clone(), res.def.map(Resolution::Def));
200 });
201 m.item_map.extern_prelude.iter().for_each(|(name, def)| { 193 m.item_map.extern_prelude.iter().for_each(|(name, def)| {
202 f(name.clone(), PerNs::types(Resolution::Def(*def))); 194 f(name.clone(), PerNs::types(Resolution::Def(*def)));
203 }); 195 });
204 } 196 }
205 Scope::GenericParams(gp) => { 197 Scope::GenericParams(gp) => {
206 for param in &gp.params { 198 for param in &gp.params {
207 f( 199 f(param.name.clone(), PerNs::types(Resolution::GenericParam(param.idx)))
208 param.name.clone(),
209 PerNs::types(Resolution::GenericParam(param.idx)),
210 )
211 } 200 }
212 } 201 }
213 Scope::ImplBlockScope(i) => { 202 Scope::ImplBlockScope(i) => {
214 f( 203 f(Name::self_type(), PerNs::types(Resolution::SelfType(i.clone())));
215 Name::self_type(),
216 PerNs::types(Resolution::SelfType(i.clone())),
217 );
218 } 204 }
219 Scope::ExprScope(e) => { 205 Scope::ExprScope(e) => {
220 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { 206 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| {
221 f( 207 f(e.name().clone(), PerNs::values(Resolution::LocalBinding(e.pat())));
222 e.name().clone(),
223 PerNs::values(Resolution::LocalBinding(e.pat())),
224 );
225 }); 208 });
226 } 209 }
227 } 210 }
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 59f782277..625a2ce45 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -65,11 +65,7 @@ pub fn module_from_child_node(
65 file_id: FileId, 65 file_id: FileId,
66 child: &SyntaxNode, 66 child: &SyntaxNode,
67) -> Option<Module> { 67) -> Option<Module> {
68 if let Some(m) = child 68 if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
69 .ancestors()
70 .filter_map(ast::Module::cast)
71 .find(|it| !it.has_semi())
72 {
73 module_from_inline(db, file_id.into(), m) 69 module_from_inline(db, file_id.into(), m)
74 } else { 70 } else {
75 module_from_file_id(db, file_id.into()) 71 module_from_file_id(db, file_id.into())
@@ -82,14 +78,13 @@ fn module_from_source(
82 decl_id: Option<SourceFileItemId>, 78 decl_id: Option<SourceFileItemId>,
83) -> Option<Module> { 79) -> Option<Module> {
84 let source_root_id = db.file_source_root(file_id.as_original_file()); 80 let source_root_id = db.file_source_root(file_id.as_original_file());
85 db.source_root_crates(source_root_id) 81 db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
86 .iter() 82 |krate| {
87 .map(|&crate_id| Crate { crate_id })
88 .find_map(|krate| {
89 let module_tree = db.module_tree(krate); 83 let module_tree = db.module_tree(krate);
90 let module_id = module_tree.find_module_by_source(file_id, decl_id)?; 84 let module_id = module_tree.find_module_by_source(file_id, decl_id)?;
91 Some(Module { krate, module_id }) 85 Some(Module { krate, module_id })
92 }) 86 },
87 )
93} 88}
94 89
95pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { 90pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
@@ -116,9 +111,7 @@ pub fn function_from_module(
116 let (file_id, _) = module.definition_source(db); 111 let (file_id, _) = module.definition_source(db);
117 let file_id = file_id.into(); 112 let file_id = file_id.into();
118 let ctx = LocationCtx::new(db, module, file_id); 113 let ctx = LocationCtx::new(db, module, file_id);
119 Function { 114 Function { id: ctx.to_def(fn_def) }
120 id: ctx.to_def(fn_def),
121 }
122} 115}
123 116
124pub fn function_from_child_node( 117pub fn function_from_child_node(
@@ -138,18 +131,14 @@ pub fn struct_from_module(
138 let (file_id, _) = module.definition_source(db); 131 let (file_id, _) = module.definition_source(db);
139 let file_id = file_id.into(); 132 let file_id = file_id.into();
140 let ctx = LocationCtx::new(db, module, file_id); 133 let ctx = LocationCtx::new(db, module, file_id);
141 Struct { 134 Struct { id: ctx.to_def(struct_def) }
142 id: ctx.to_def(struct_def),
143 }
144} 135}
145 136
146pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { 137pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
147 let (file_id, _) = module.definition_source(db); 138 let (file_id, _) = module.definition_source(db);
148 let file_id = file_id.into(); 139 let file_id = file_id.into();
149 let ctx = LocationCtx::new(db, module, file_id); 140 let ctx = LocationCtx::new(db, module, file_id);
150 Enum { 141 Enum { id: ctx.to_def(enum_def) }
151 id: ctx.to_def(enum_def),
152 }
153} 142}
154 143
155pub fn trait_from_module( 144pub fn trait_from_module(
@@ -160,9 +149,7 @@ pub fn trait_from_module(
160 let (file_id, _) = module.definition_source(db); 149 let (file_id, _) = module.definition_source(db);
161 let file_id = file_id.into(); 150 let file_id = file_id.into();
162 let ctx = LocationCtx::new(db, module, file_id); 151 let ctx = LocationCtx::new(db, module, file_id);
163 Trait { 152 Trait { id: ctx.to_def(trait_def) }
164 id: ctx.to_def(trait_def),
165 }
166} 153}
167 154
168pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { 155pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 86a7f8b83..453520bbe 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -305,10 +305,8 @@ impl Ty {
305 match type_ref { 305 match type_ref {
306 TypeRef::Never => Ty::Never, 306 TypeRef::Never => Ty::Never,
307 TypeRef::Tuple(inner) => { 307 TypeRef::Tuple(inner) => {
308 let inner_tys = inner 308 let inner_tys =
309 .iter() 309 inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
310 .map(|tr| Ty::from_hir(db, resolver, tr))
311 .collect::<Vec<_>>();
312 Ty::Tuple(inner_tys.into()) 310 Ty::Tuple(inner_tys.into())
313 } 311 }
314 TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), 312 TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path),
@@ -330,17 +328,11 @@ impl Ty {
330 } 328 }
331 TypeRef::Placeholder => Ty::Unknown, 329 TypeRef::Placeholder => Ty::Unknown,
332 TypeRef::Fn(params) => { 330 TypeRef::Fn(params) => {
333 let mut inner_tys = params 331 let mut inner_tys =
334 .iter() 332 params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
335 .map(|tr| Ty::from_hir(db, resolver, tr)) 333 let return_ty =
336 .collect::<Vec<_>>(); 334 inner_tys.pop().expect("TypeRef::Fn should always have at least return type");
337 let return_ty = inner_tys 335 let sig = FnSig { input: inner_tys, output: return_ty };
338 .pop()
339 .expect("TypeRef::Fn should always have at least return type");
340 let sig = FnSig {
341 input: inner_tys,
342 output: return_ty,
343 };
344 Ty::FnPtr(Arc::new(sig)) 336 Ty::FnPtr(Arc::new(sig))
345 } 337 }
346 TypeRef::Error => Ty::Unknown, 338 TypeRef::Error => Ty::Unknown,
@@ -407,10 +399,7 @@ impl Ty {
407 resolved: TypableDef, 399 resolved: TypableDef,
408 ) -> Substs { 400 ) -> Substs {
409 let mut substs = Vec::new(); 401 let mut substs = Vec::new();
410 let last = path 402 let last = path.segments.last().expect("path should have at least one segment");
411 .segments
412 .last()
413 .expect("path should have at least one segment");
414 let (def_generics, segment) = match resolved { 403 let (def_generics, segment) = match resolved {
415 TypableDef::Function(func) => (func.generic_params(db), last), 404 TypableDef::Function(func) => (func.generic_params(db), last),
416 TypableDef::Struct(s) => (s.generic_params(db), last), 405 TypableDef::Struct(s) => (s.generic_params(db), last),
@@ -447,11 +436,8 @@ impl Ty {
447 } 436 }
448 // add placeholders for args that were not provided 437 // add placeholders for args that were not provided
449 // TODO: handle defaults 438 // TODO: handle defaults
450 let supplied_params = segment 439 let supplied_params =
451 .args_and_bindings 440 segment.args_and_bindings.as_ref().map(|ga| ga.args.len()).unwrap_or(0);
452 .as_ref()
453 .map(|ga| ga.args.len())
454 .unwrap_or(0);
455 for _ in supplied_params..def_generics.params.len() { 441 for _ in supplied_params..def_generics.params.len() {
456 substs.push(Ty::Unknown); 442 substs.push(Ty::Unknown);
457 } 443 }
@@ -531,17 +517,8 @@ impl Ty {
531 /// `Option<u32>` afterwards.) 517 /// `Option<u32>` afterwards.)
532 pub fn apply_substs(self, substs: Substs) -> Ty { 518 pub fn apply_substs(self, substs: Substs) -> Ty {
533 match self { 519 match self {
534 Ty::Adt { def_id, name, .. } => Ty::Adt { 520 Ty::Adt { def_id, name, .. } => Ty::Adt { def_id, name, substs },
535 def_id, 521 Ty::FnDef { def, name, sig, .. } => Ty::FnDef { def, name, sig, substs },
536 name,
537 substs,
538 },
539 Ty::FnDef { def, name, sig, .. } => Ty::FnDef {
540 def,
541 name,
542 sig,
543 substs,
544 },
545 _ => self, 522 _ => self,
546 } 523 }
547 } 524 }
@@ -591,42 +568,25 @@ impl fmt::Display for Ty {
591 if ts.len() == 1 { 568 if ts.len() == 1 {
592 write!(f, "({},)", ts[0]) 569 write!(f, "({},)", ts[0])
593 } else { 570 } else {
594 join(ts.iter()) 571 join(ts.iter()).surround_with("(", ")").separator(", ").to_fmt(f)
595 .surround_with("(", ")")
596 .separator(", ")
597 .to_fmt(f)
598 } 572 }
599 } 573 }
600 Ty::FnPtr(sig) => { 574 Ty::FnPtr(sig) => {
601 join(sig.input.iter()) 575 join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?;
602 .surround_with("fn(", ")")
603 .separator(", ")
604 .to_fmt(f)?;
605 write!(f, " -> {}", sig.output) 576 write!(f, " -> {}", sig.output)
606 } 577 }
607 Ty::FnDef { 578 Ty::FnDef { name, substs, sig, .. } => {
608 name, substs, sig, ..
609 } => {
610 write!(f, "fn {}", name)?; 579 write!(f, "fn {}", name)?;
611 if substs.0.len() > 0 { 580 if substs.0.len() > 0 {
612 join(substs.0.iter()) 581 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?;
613 .surround_with("<", ">")
614 .separator(", ")
615 .to_fmt(f)?;
616 } 582 }
617 join(sig.input.iter()) 583 join(sig.input.iter()).surround_with("(", ")").separator(", ").to_fmt(f)?;
618 .surround_with("(", ")")
619 .separator(", ")
620 .to_fmt(f)?;
621 write!(f, " -> {}", sig.output) 584 write!(f, " -> {}", sig.output)
622 } 585 }
623 Ty::Adt { name, substs, .. } => { 586 Ty::Adt { name, substs, .. } => {
624 write!(f, "{}", name)?; 587 write!(f, "{}", name)?;
625 if substs.0.len() > 0 { 588 if substs.0.len() > 0 {
626 join(substs.0.iter()) 589 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?;
627 .surround_with("<", ">")
628 .separator(", ")
629 .to_fmt(f)?;
630 } 590 }
631 Ok(()) 591 Ok(())
632 } 592 }
@@ -646,31 +606,16 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
646 let resolver = def.resolver(db); 606 let resolver = def.resolver(db);
647 let generics = def.generic_params(db); 607 let generics = def.generic_params(db);
648 let name = def.name(db); 608 let name = def.name(db);
649 let input = signature 609 let input =
650 .params() 610 signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
651 .iter()
652 .map(|tr| Ty::from_hir(db, &resolver, tr))
653 .collect::<Vec<_>>();
654 let output = Ty::from_hir(db, &resolver, signature.ret_type()); 611 let output = Ty::from_hir(db, &resolver, signature.ret_type());
655 let sig = Arc::new(FnSig { input, output }); 612 let sig = Arc::new(FnSig { input, output });
656 let substs = make_substs(&generics); 613 let substs = make_substs(&generics);
657 Ty::FnDef { 614 Ty::FnDef { def, sig, name, substs }
658 def,
659 sig,
660 name,
661 substs,
662 }
663} 615}
664 616
665fn make_substs(generics: &GenericParams) -> Substs { 617fn make_substs(generics: &GenericParams) -> Substs {
666 Substs( 618 Substs(generics.params.iter().map(|_p| Ty::Unknown).collect::<Vec<_>>().into())
667 generics
668 .params
669 .iter()
670 .map(|_p| Ty::Unknown)
671 .collect::<Vec<_>>()
672 .into(),
673 )
674} 619}
675 620
676fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 621fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
@@ -935,11 +880,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
935 } 880 }
936 881
937 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool { 882 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool {
938 substs1 883 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify(t1, t2))
939 .0
940 .iter()
941 .zip(substs2.0.iter())
942 .all(|(t1, t2)| self.unify(t1, t2))
943 } 884 }
944 885
945 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 886 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
@@ -961,25 +902,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
961 }, 902 },
962 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, 903 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2,
963 ( 904 (
964 Ty::Adt { 905 Ty::Adt { def_id: def_id1, substs: substs1, .. },
965 def_id: def_id1, 906 Ty::Adt { def_id: def_id2, substs: substs2, .. },
966 substs: substs1,
967 ..
968 },
969 Ty::Adt {
970 def_id: def_id2,
971 substs: substs2,
972 ..
973 },
974 ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2), 907 ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2),
975 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), 908 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2),
976 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), 909 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2),
977 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), 910 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2),
978 (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, 911 (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true,
979 (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => ts1 912 (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => {
980 .iter() 913 ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify(t1, t2))
981 .zip(ts2.iter()) 914 }
982 .all(|(t1, t2)| self.unify(t1, t2)),
983 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) 915 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
984 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) 916 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
985 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { 917 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => {
@@ -994,8 +926,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
994 | (Ty::Infer(InferTy::FloatVar(tv)), other) 926 | (Ty::Infer(InferTy::FloatVar(tv)), other)
995 | (other, Ty::Infer(InferTy::FloatVar(tv))) => { 927 | (other, Ty::Infer(InferTy::FloatVar(tv))) => {
996 // the type var is unknown since we tried to resolve it 928 // the type var is unknown since we tried to resolve it
997 self.var_unification_table 929 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
998 .union_value(*tv, TypeVarValue::Known(other.clone()));
999 true 930 true
1000 } 931 }
1001 _ => false, 932 _ => false,
@@ -1003,21 +934,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1003 } 934 }
1004 935
1005 fn new_type_var(&mut self) -> Ty { 936 fn new_type_var(&mut self) -> Ty {
1006 Ty::Infer(InferTy::TypeVar( 937 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
1007 self.var_unification_table.new_key(TypeVarValue::Unknown),
1008 ))
1009 } 938 }
1010 939
1011 fn new_integer_var(&mut self) -> Ty { 940 fn new_integer_var(&mut self) -> Ty {
1012 Ty::Infer(InferTy::IntVar( 941 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
1013 self.var_unification_table.new_key(TypeVarValue::Unknown),
1014 ))
1015 } 942 }
1016 943
1017 fn new_float_var(&mut self) -> Ty { 944 fn new_float_var(&mut self) -> Ty {
1018 Ty::Infer(InferTy::FloatVar( 945 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
1019 self.var_unification_table.new_key(TypeVarValue::Unknown),
1020 ))
1021 } 946 }
1022 947
1023 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 948 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
@@ -1207,9 +1132,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1207 1132
1208 for subpat in subpats { 1133 for subpat in subpats {
1209 let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); 1134 let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
1210 let expected_ty = matching_field 1135 let expected_ty =
1211 .map_or(Ty::Unknown, |field| field.ty(self.db)) 1136 matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs);
1212 .subst(&substs);
1213 self.infer_pat(subpat.pat, &expected_ty); 1137 self.infer_pat(subpat.pat, &expected_ty);
1214 } 1138 }
1215 1139
@@ -1249,25 +1173,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1249 let subty = self.infer_pat(*pat, expectation); 1173 let subty = self.infer_pat(*pat, expectation);
1250 Ty::Ref(subty.into(), *mutability) 1174 Ty::Ref(subty.into(), *mutability)
1251 } 1175 }
1252 Pat::TupleStruct { 1176 Pat::TupleStruct { path: ref p, args: ref subpats } => {
1253 path: ref p, 1177 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected)
1254 args: ref subpats, 1178 }
1255 } => self.infer_tuple_struct_pat(p.as_ref(), subpats, expected), 1179 Pat::Struct { path: ref p, args: ref fields } => {
1256 Pat::Struct { 1180 self.infer_struct_pat(p.as_ref(), fields, expected)
1257 path: ref p, 1181 }
1258 args: ref fields,
1259 } => self.infer_struct_pat(p.as_ref(), fields, expected),
1260 Pat::Path(path) => { 1182 Pat::Path(path) => {
1261 // TODO use correct resolver for the surrounding expression 1183 // TODO use correct resolver for the surrounding expression
1262 let resolver = self.resolver.clone(); 1184 let resolver = self.resolver.clone();
1263 self.infer_path_expr(&resolver, &path) 1185 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown)
1264 .unwrap_or(Ty::Unknown) 1186 }
1265 } 1187 Pat::Bind { mode, name: _name, subpat } => {
1266 Pat::Bind {
1267 mode,
1268 name: _name,
1269 subpat,
1270 } => {
1271 let subty = if let Some(subpat) = subpat { 1188 let subty = if let Some(subpat) = subpat {
1272 self.infer_pat(*subpat, expected) 1189 self.infer_pat(*subpat, expected)
1273 } else { 1190 } else {
@@ -1294,11 +1211,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1294 let body = Arc::clone(&self.body); // avoid borrow checker problem 1211 let body = Arc::clone(&self.body); // avoid borrow checker problem
1295 let ty = match &body[tgt_expr] { 1212 let ty = match &body[tgt_expr] {
1296 Expr::Missing => Ty::Unknown, 1213 Expr::Missing => Ty::Unknown,
1297 Expr::If { 1214 Expr::If { condition, then_branch, else_branch } => {
1298 condition,
1299 then_branch,
1300 else_branch,
1301 } => {
1302 // if let is desugared to match, so this is always simple if 1215 // if let is desugared to match, so this is always simple if
1303 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); 1216 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
1304 let then_ty = self.infer_expr(*then_branch, expected); 1217 let then_ty = self.infer_expr(*then_branch, expected);
@@ -1325,21 +1238,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1325 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 1238 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
1326 Ty::unit() 1239 Ty::unit()
1327 } 1240 }
1328 Expr::For { 1241 Expr::For { iterable, body, pat } => {
1329 iterable,
1330 body,
1331 pat,
1332 } => {
1333 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 1242 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none());
1334 self.infer_pat(*pat, &Ty::Unknown); 1243 self.infer_pat(*pat, &Ty::Unknown);
1335 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 1244 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
1336 Ty::unit() 1245 Ty::unit()
1337 } 1246 }
1338 Expr::Lambda { 1247 Expr::Lambda { body, args, arg_types } => {
1339 body,
1340 args,
1341 arg_types,
1342 } => {
1343 assert_eq!(args.len(), arg_types.len()); 1248 assert_eq!(args.len(), arg_types.len());
1344 1249
1345 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { 1250 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
@@ -1362,11 +1267,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1362 Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), 1267 Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
1363 Ty::FnDef { substs, sig, .. } => { 1268 Ty::FnDef { substs, sig, .. } => {
1364 let ret_ty = sig.output.clone().subst(&substs); 1269 let ret_ty = sig.output.clone().subst(&substs);
1365 let param_tys = sig 1270 let param_tys =
1366 .input 1271 sig.input.iter().map(|ty| ty.clone().subst(&substs)).collect();
1367 .iter()
1368 .map(|ty| ty.clone().subst(&substs))
1369 .collect();
1370 (param_tys, ret_ty) 1272 (param_tys, ret_ty)
1371 } 1273 }
1372 _ => { 1274 _ => {
@@ -1381,11 +1283,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1381 } 1283 }
1382 ret_ty 1284 ret_ty
1383 } 1285 }
1384 Expr::MethodCall { 1286 Expr::MethodCall { receiver, args, method_name } => {
1385 receiver,
1386 args,
1387 method_name,
1388 } => {
1389 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 1287 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
1390 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 1288 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
1391 let method_ty = match resolved { 1289 let method_ty = match resolved {
@@ -1399,11 +1297,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1399 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1297 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
1400 Ty::FnPtr(sig) => { 1298 Ty::FnPtr(sig) => {
1401 if !sig.input.is_empty() { 1299 if !sig.input.is_empty() {
1402 ( 1300 (sig.input[0].clone(), sig.input[1..].to_vec(), sig.output.clone())
1403 sig.input[0].clone(),
1404 sig.input[1..].to_vec(),
1405 sig.output.clone(),
1406 )
1407 } else { 1301 } else {
1408 (Ty::Unknown, Vec::new(), sig.output.clone()) 1302 (Ty::Unknown, Vec::new(), sig.output.clone())
1409 } 1303 }
@@ -1469,11 +1363,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1469 } 1363 }
1470 Ty::Never 1364 Ty::Never
1471 } 1365 }
1472 Expr::StructLit { 1366 Expr::StructLit { path, fields, spread } => {
1473 path,
1474 fields,
1475 spread,
1476 } => {
1477 let (ty, def_id) = self.resolve_variant(path.as_ref()); 1367 let (ty, def_id) = self.resolve_variant(path.as_ref());
1478 let substs = ty.substs().unwrap_or_else(Substs::empty); 1368 let substs = ty.substs().unwrap_or_else(Substs::empty);
1479 for field in fields { 1369 for field in fields {
@@ -1497,14 +1387,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1497 let i = name.to_string().parse::<usize>().ok(); 1387 let i = name.to_string().parse::<usize>().ok();
1498 i.and_then(|i| fields.get(i).cloned()) 1388 i.and_then(|i| fields.get(i).cloned())
1499 } 1389 }
1500 Ty::Adt { 1390 Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => {
1501 def_id: AdtDef::Struct(s), 1391 s.field(self.db, name).map(|field| {
1502 ref substs, 1392 self.write_field_resolution(tgt_expr, field);
1503 .. 1393 field.ty(self.db).subst(substs)
1504 } => s.field(self.db, name).map(|field| { 1394 })
1505 self.write_field_resolution(tgt_expr, field); 1395 }
1506 field.ty(self.db).subst(substs)
1507 }),
1508 _ => None, 1396 _ => None,
1509 }) 1397 })
1510 .unwrap_or(Ty::Unknown); 1398 .unwrap_or(Ty::Unknown);
@@ -1635,15 +1523,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1635 ) -> Ty { 1523 ) -> Ty {
1636 for stmt in statements { 1524 for stmt in statements {
1637 match stmt { 1525 match stmt {
1638 Statement::Let { 1526 Statement::Let { pat, type_ref, initializer } => {
1639 pat, 1527 let decl_ty =
1640 type_ref, 1528 type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown);
1641 initializer,
1642 } => {
1643 let decl_ty = type_ref
1644 .as_ref()
1645 .map(|tr| self.make_ty(tr))
1646 .unwrap_or(Ty::Unknown);
1647 let decl_ty = self.insert_type_vars(decl_ty); 1529 let decl_ty = self.insert_type_vars(decl_ty);
1648 let ty = if let Some(expr) = initializer { 1530 let ty = if let Some(expr) = initializer {
1649 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); 1531 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
@@ -1659,11 +1541,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1659 } 1541 }
1660 } 1542 }
1661 } 1543 }
1662 let ty = if let Some(expr) = tail { 1544 let ty = if let Some(expr) = tail { self.infer_expr(expr, expected) } else { Ty::unit() };
1663 self.infer_expr(expr, expected)
1664 } else {
1665 Ty::unit()
1666 };
1667 ty 1545 ty
1668 } 1546 }
1669 1547
@@ -1678,10 +1556,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1678 } 1556 }
1679 1557
1680 fn infer_body(&mut self) { 1558 fn infer_body(&mut self) {
1681 self.infer_expr( 1559 self.infer_expr(self.body.body_expr(), &Expectation::has_type(self.return_ty.clone()));
1682 self.body.body_expr(),
1683 &Expectation::has_type(self.return_ty.clone()),
1684 );
1685 } 1560 }
1686} 1561}
1687 1562
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index a7d4517ee..da7587f01 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -46,18 +46,13 @@ impl CrateImplBlocks {
46 ty: &Ty, 46 ty: &Ty,
47 ) -> impl Iterator<Item = (Module, 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.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map(
50 .and_then(|f| self.impls.get(&f)) 50 move |(module_id, impl_id)| {
51 .into_iter() 51 let module = Module { krate: self.krate, module_id: *module_id };
52 .flat_map(|i| i.iter())
53 .map(move |(module_id, impl_id)| {
54 let module = Module {
55 krate: self.krate,
56 module_id: *module_id,
57 };
58 let module_impl_blocks = db.impls_in_module(module); 52 let module_impl_blocks = db.impls_in_module(module);
59 (module, ImplBlock::from_id(module_impl_blocks, *impl_id)) 53 (module, ImplBlock::from_id(module_impl_blocks, *impl_id))
60 }) 54 },
55 )
61 } 56 }
62 57
63 pub fn lookup_impl_blocks_for_trait<'a>( 58 pub fn lookup_impl_blocks_for_trait<'a>(
@@ -66,18 +61,13 @@ impl CrateImplBlocks {
66 tr: &Trait, 61 tr: &Trait,
67 ) -> impl Iterator<Item = (Module, ImplBlock)> + 'a { 62 ) -> impl Iterator<Item = (Module, ImplBlock)> + 'a {
68 let id = tr.id; 63 let id = tr.id;
69 self.impls_by_trait 64 self.impls_by_trait.get(&id).into_iter().flat_map(|i| i.iter()).map(
70 .get(&id) 65 move |(module_id, impl_id)| {
71 .into_iter() 66 let module = Module { krate: self.krate, module_id: *module_id };
72 .flat_map(|i| i.iter())
73 .map(move |(module_id, impl_id)| {
74 let module = Module {
75 krate: self.krate,
76 module_id: *module_id,
77 };
78 let module_impl_blocks = db.impls_in_module(module); 67 let module_impl_blocks = db.impls_in_module(module);
79 (module, ImplBlock::from_id(module_impl_blocks, *impl_id)) 68 (module, ImplBlock::from_id(module_impl_blocks, *impl_id))
80 }) 69 },
70 )
81 } 71 }
82 72
83 fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { 73 fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 30da8fc23..2621d1b55 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -634,11 +634,7 @@ fn infer(content: &str) -> String {
634 let (db, _, file_id) = MockDatabase::with_single_file(content); 634 let (db, _, file_id) = MockDatabase::with_single_file(content);
635 let source_file = db.parse(file_id); 635 let source_file = db.parse(file_id);
636 let mut acc = String::new(); 636 let mut acc = String::new();
637 for fn_def in source_file 637 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) {
638 .syntax()
639 .descendants()
640 .filter_map(ast::FnDef::cast)
641 {
642 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); 638 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
643 let inference_result = func.infer(&db); 639 let inference_result = func.infer(&db);
644 let body_syntax_mapping = func.body_syntax_mapping(&db); 640 let body_syntax_mapping = func.body_syntax_mapping(&db);
@@ -725,8 +721,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
725 " 721 "
726 .to_string(); 722 .to_string();
727 723
728 db.query_mut(ra_db::FileTextQuery) 724 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text));
729 .set(pos.file_id, Arc::new(new_text));
730 725
731 { 726 {
732 let events = db.log_executed(|| { 727 let events = db.log_executed(|| {
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs
index c9db4e0a5..ee8b7376a 100644
--- a/crates/ra_hir/src/type_ref.rs
+++ b/crates/ra_hir/src/type_ref.rs
@@ -62,11 +62,9 @@ impl TypeRef {
62 ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 62 ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
63 TupleType(inner) => TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()), 63 TupleType(inner) => TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()),
64 NeverType(..) => TypeRef::Never, 64 NeverType(..) => TypeRef::Never,
65 PathType(inner) => inner 65 PathType(inner) => {
66 .path() 66 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error)
67 .and_then(Path::from_ast) 67 }
68 .map(TypeRef::Path)
69 .unwrap_or(TypeRef::Error),
70 PointerType(inner) => { 68 PointerType(inner) => {
71 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 69 let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
72 let mutability = Mutability::from_mutable(inner.is_mut()); 70 let mutability = Mutability::from_mutable(inner.is_mut());
@@ -83,10 +81,7 @@ impl TypeRef {
83 FnPointerType(inner) => { 81 FnPointerType(inner) => {
84 let ret_ty = TypeRef::from_ast_opt(inner.ret_type().and_then(|rt| rt.type_ref())); 82 let ret_ty = TypeRef::from_ast_opt(inner.ret_type().and_then(|rt| rt.type_ref()));
85 let mut params = if let Some(pl) = inner.param_list() { 83 let mut params = if let Some(pl) = inner.param_list() {
86 pl.params() 84 pl.params().map(|p| p.type_ref()).map(TypeRef::from_ast_opt).collect()
87 .map(|p| p.type_ref())
88 .map(TypeRef::from_ast_opt)
89 .collect()
90 } else { 85 } else {
91 Vec::new() 86 Vec::new()
92 }; 87 };
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide_api/src/assists.rs
index 2a96fdf47..7a9c66681 100644
--- a/crates/ra_ide_api/src/assists.rs
+++ b/crates/ra_ide_api/src/assists.rs
@@ -7,10 +7,7 @@ pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<SourceChange>
7 .into_iter() 7 .into_iter()
8 .map(|(label, action)| { 8 .map(|(label, action)| {
9 let file_id = frange.file_id; 9 let file_id = frange.file_id;
10 let file_edit = SourceFileEdit { 10 let file_edit = SourceFileEdit { file_id, edit: action.edit };
11 file_id,
12 edit: action.edit,
13 };
14 SourceChange { 11 SourceChange {
15 label: label.label, 12 label: label.label,
16 source_file_edits: vec![file_edit], 13 source_file_edits: vec![file_edit],
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index a59ab7853..1b279615c 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -21,9 +21,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
21 21
22 // Resolve the function's NameRef (NOTE: this isn't entirely accurate). 22 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
23 let file_symbols = crate::symbol_index::index_resolve(db, name_ref); 23 let file_symbols = crate::symbol_index::index_resolve(db, name_ref);
24 let symbol = file_symbols 24 let symbol = file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)?;
25 .into_iter()
26 .find(|it| it.ptr.kind() == FN_DEF)?;
27 let fn_file = db.parse(symbol.file_id); 25 let fn_file = db.parse(symbol.file_id);
28 let fn_def = symbol.ptr.to_node(&fn_file); 26 let fn_def = symbol.ptr.to_node(&fn_file);
29 let fn_def = ast::FnDef::cast(fn_def).unwrap(); 27 let fn_def = ast::FnDef::cast(fn_def).unwrap();
@@ -53,13 +51,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
53 let start = arg_list_range.start(); 51 let start = arg_list_range.start();
54 52
55 let range_search = TextRange::from_to(start, position.offset); 53 let range_search = TextRange::from_to(start, position.offset);
56 let mut commas: usize = arg_list 54 let mut commas: usize =
57 .syntax() 55 arg_list.syntax().text().slice(range_search).to_string().matches(',').count();
58 .text()
59 .slice(range_search)
60 .to_string()
61 .matches(',')
62 .count();
63 56
64 // If we have a method call eat the first param since it's just self. 57 // If we have a method call eat the first param since it's just self.
65 if has_self { 58 if has_self {
@@ -96,11 +89,9 @@ impl<'a> FnCallNode<'a> {
96 _ => return None, 89 _ => return None,
97 }), 90 }),
98 91
99 FnCallNode::MethodCallExpr(call_expr) => call_expr 92 FnCallNode::MethodCallExpr(call_expr) => {
100 .syntax() 93 call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
101 .children() 94 }
102 .filter_map(ast::NameRef::cast)
103 .nth(0),
104 } 95 }
105 } 96 }
106 97
@@ -117,12 +108,7 @@ impl CallInfo {
117 let label = crate::completion::function_label(node)?; 108 let label = crate::completion::function_label(node)?;
118 let doc = function.docs(db); 109 let doc = function.docs(db);
119 110
120 Some(CallInfo { 111 Some(CallInfo { parameters: param_list(node), label, doc, active_parameter: None })
121 parameters: param_list(node),
122 label,
123 doc,
124 active_parameter: None,
125 })
126 } 112 }
127} 113}
128 114
@@ -136,10 +122,7 @@ fn param_list(node: &ast::FnDef) -> Vec<String> {
136 // Maybe use param.pat here? See if we can just extract the name? 122 // Maybe use param.pat here? See if we can just extract the name?
137 //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); 123 //res.extend(param_list.params().map(|p| p.syntax().text().to_string()));
138 res.extend( 124 res.extend(
139 param_list 125 param_list.params().filter_map(|p| p.pat()).map(|pat| pat.syntax().text().to_string()),
140 .params()
141 .filter_map(|p| p.pat())
142 .map(|pat| pat.syntax().text().to_string()),
143 ); 126 );
144 } 127 }
145 res 128 res
@@ -378,10 +361,7 @@ pub fn foo() {
378"#, 361"#,
379 ); 362 );
380 363
381 assert_eq!( 364 assert_eq!(info.parameters, vec!["&mut self".to_string(), "ctx".to_string()]);
382 info.parameters,
383 vec!["&mut self".to_string(), "ctx".to_string()]
384 );
385 assert_eq!(info.active_parameter, Some(1)); 365 assert_eq!(info.active_parameter, Some(1));
386 assert_eq!( 366 assert_eq!(
387 info.doc.map(|it| it.into()), 367 info.doc.map(|it| it.into()),
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 992955740..3f041f9c3 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -65,16 +65,8 @@ impl AnalysisChange {
65 path: RelativePathBuf, 65 path: RelativePathBuf,
66 text: Arc<String>, 66 text: Arc<String>,
67 ) { 67 ) {
68 let file = AddFile { 68 let file = AddFile { file_id, path, text };
69 file_id, 69 self.roots_changed.entry(root_id).or_default().added.push(file);
70 path,
71 text,
72 };
73 self.roots_changed
74 .entry(root_id)
75 .or_default()
76 .added
77 .push(file);
78 } 70 }
79 71
80 pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) { 72 pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
@@ -83,11 +75,7 @@ impl AnalysisChange {
83 75
84 pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) { 76 pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
85 let file = RemoveFile { file_id, path }; 77 let file = RemoveFile { file_id, path };
86 self.roots_changed 78 self.roots_changed.entry(root_id).or_default().removed.push(file);
87 .entry(root_id)
88 .or_default()
89 .removed
90 .push(file);
91 } 79 }
92 80
93 pub fn add_library(&mut self, data: LibraryData) { 81 pub fn add_library(&mut self, data: LibraryData) {
@@ -155,17 +143,9 @@ impl LibraryData {
155 let mut root_change = RootChange::default(); 143 let mut root_change = RootChange::default();
156 root_change.added = files 144 root_change.added = files
157 .into_iter() 145 .into_iter()
158 .map(|(file_id, path, text)| AddFile { 146 .map(|(file_id, path, text)| AddFile { file_id, path, text })
159 file_id,
160 path,
161 text,
162 })
163 .collect(); 147 .collect();
164 LibraryData { 148 LibraryData { root_id, root_change, symbol_index }
165 root_id,
166 root_change,
167 symbol_index,
168 }
169 } 149 }
170} 150}
171 151
@@ -226,10 +206,7 @@ impl RootDatabase {
226 self.last_gc_check = time::Instant::now(); 206 self.last_gc_check = time::Instant::now();
227 let retained_trees = syntax_tree_stats(self).retained; 207 let retained_trees = syntax_tree_stats(self).retained;
228 if retained_trees > 100 { 208 if retained_trees > 100 {
229 log::info!( 209 log::info!("automatic garbadge collection, {} retained trees", retained_trees);
230 "automatic garbadge collection, {} retained trees",
231 retained_trees
232 );
233 self.collect_garbage(); 210 self.collect_garbage();
234 } 211 }
235 } 212 }
@@ -238,9 +215,7 @@ impl RootDatabase {
238 pub(crate) fn collect_garbage(&mut self) { 215 pub(crate) fn collect_garbage(&mut self) {
239 self.last_gc = time::Instant::now(); 216 self.last_gc = time::Instant::now();
240 217
241 let sweep = SweepStrategy::default() 218 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
242 .discard_values()
243 .sweep_all_revisions();
244 219
245 self.query(ra_db::ParseQuery).sweep(sweep); 220 self.query(ra_db::ParseQuery).sweep(sweep);
246 221
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index bad51cc51..a673dbdcf 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -25,9 +25,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
25fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 25fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
26 for receiver in receiver.autoderef(ctx.db) { 26 for receiver in receiver.autoderef(ctx.db) {
27 match receiver { 27 match receiver {
28 Ty::Adt { 28 Ty::Adt { def_id, ref substs, .. } => {
29 def_id, ref substs, ..
30 } => {
31 match def_id { 29 match def_id {
32 AdtDef::Struct(s) => { 30 AdtDef::Struct(s) => {
33 for field in s.fields(ctx.db) { 31 for field in s.fields(ctx.db) {
diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs
index 8d4df4ea1..43532226f 100644
--- a/crates/ra_ide_api/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs
@@ -43,13 +43,12 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
43 node: &'a N, 43 node: &'a N,
44 params: &mut FxHashMap<String, (u32, &'a ast::Param)>, 44 params: &mut FxHashMap<String, (u32, &'a ast::Param)>,
45 ) { 45 ) {
46 node.functions() 46 node.functions().filter_map(|it| it.param_list()).flat_map(|it| it.params()).for_each(
47 .filter_map(|it| it.param_list()) 47 |param| {
48 .flat_map(|it| it.params())
49 .for_each(|param| {
50 let text = param.syntax().text().to_string(); 48 let text = param.syntax().text().to_string();
51 params.entry(text).or_insert((0, param)).0 += 1; 49 params.entry(text).or_insert((0, param)).0 += 1;
52 }) 50 },
51 )
53 } 52 }
54} 53}
55 54
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 0b9948d4b..c47a14e9f 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -31,14 +31,10 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
31 hir::ModuleDef::Enum(e) => { 31 hir::ModuleDef::Enum(e) => {
32 e.variants(ctx.db).into_iter().for_each(|variant| { 32 e.variants(ctx.db).into_iter().for_each(|variant| {
33 if let Some(name) = variant.name(ctx.db) { 33 if let Some(name) = variant.name(ctx.db) {
34 let detail_types = variant 34 let detail_types =
35 .fields(ctx.db) 35 variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db));
36 .into_iter() 36 let detail =
37 .map(|field| field.ty(ctx.db)); 37 join(detail_types).separator(", ").surround_with("(", ")").to_string();
38 let detail = join(detail_types)
39 .separator(", ")
40 .surround_with("(", ")")
41 .to_string();
42 38
43 CompletionItem::new( 39 CompletionItem::new(
44 CompletionKind::Reference, 40 CompletionKind::Reference,
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index e3a739d6d..10a3c8db7 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -17,11 +17,7 @@ use ra_text_edit::TextEditBuilder;
17 17
18fn postfix_snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder { 18fn postfix_snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder {
19 let replace_range = ctx.source_range(); 19 let replace_range = ctx.source_range();
20 let receiver_range = ctx 20 let receiver_range = ctx.dot_receiver.expect("no receiver available").syntax().range();
21 .dot_receiver
22 .expect("no receiver available")
23 .syntax()
24 .range();
25 let delete_range = TextRange::from_to(receiver_range.start(), replace_range.start()); 21 let delete_range = TextRange::from_to(receiver_range.start(), replace_range.start());
26 let mut builder = TextEditBuilder::default(); 22 let mut builder = TextEditBuilder::default();
27 builder.delete(delete_range); 23 builder.delete(delete_range);
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 8674b1e66..445788407 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -7,13 +7,9 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
7 let names = ctx.resolver.all_names(); 7 let names = ctx.resolver.all_names();
8 8
9 names.into_iter().for_each(|(name, res)| { 9 names.into_iter().for_each(|(name, res)| {
10 CompletionItem::new( 10 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
11 CompletionKind::Reference, 11 .from_resolution(ctx, &res)
12 ctx.source_range(), 12 .add_to(acc)
13 name.to_string(),
14 )
15 .from_resolution(ctx, &res)
16 .add_to(acc)
17 }); 13 });
18} 14}
19 15
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 8abab0221..82bd4d606 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -108,12 +108,8 @@ impl<'a> CompletionContext<'a> {
108 } 108 }
109 fn classify_name_ref(&mut self, original_file: &'a SourceFile, name_ref: &ast::NameRef) { 109 fn classify_name_ref(&mut self, original_file: &'a SourceFile, name_ref: &ast::NameRef) {
110 let name_range = name_ref.syntax().range(); 110 let name_range = name_ref.syntax().range();
111 let top_node = name_ref 111 let top_node =
112 .syntax() 112 name_ref.syntax().ancestors().take_while(|it| it.range() == name_range).last().unwrap();
113 .ancestors()
114 .take_while(|it| it.range() == name_range)
115 .last()
116 .unwrap();
117 113
118 match top_node.parent().map(|it| it.kind()) { 114 match top_node.parent().map(|it| it.kind()) {
119 Some(SOURCE_FILE) | Some(ITEM_LIST) => { 115 Some(SOURCE_FILE) | Some(ITEM_LIST) => {
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index 92e6e78bf..7b8972af0 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -105,10 +105,7 @@ impl CompletionItem {
105 } 105 }
106 /// What string is used for filtering. 106 /// What string is used for filtering.
107 pub fn lookup(&self) -> &str { 107 pub fn lookup(&self) -> &str {
108 self.lookup 108 self.lookup.as_ref().map(|it| it.as_str()).unwrap_or_else(|| self.label())
109 .as_ref()
110 .map(|it| it.as_str())
111 .unwrap_or_else(|| self.label())
112 } 109 }
113 110
114 pub fn insert_text_format(&self) -> InsertTextFormat { 111 pub fn insert_text_format(&self) -> InsertTextFormat {
@@ -214,10 +211,7 @@ impl Builder {
214 ) -> Builder { 211 ) -> Builder {
215 use hir::ModuleDef::*; 212 use hir::ModuleDef::*;
216 213
217 let def = resolution 214 let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values());
218 .as_ref()
219 .take_types()
220 .or_else(|| resolution.as_ref().take_values());
221 let def = match def { 215 let def = match def {
222 None => return self, 216 None => return self,
223 Some(it) => it, 217 Some(it) => it,
@@ -323,10 +317,8 @@ pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind
323 }; 317 };
324 let completions = completions(&analysis.db, position).unwrap(); 318 let completions = completions(&analysis.db, position).unwrap();
325 let completion_items: Vec<CompletionItem> = completions.into(); 319 let completion_items: Vec<CompletionItem> = completions.into();
326 let mut kind_completions: Vec<CompletionItem> = completion_items 320 let mut kind_completions: Vec<CompletionItem> =
327 .into_iter() 321 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
328 .filter(|c| c.completion_kind == kind)
329 .collect();
330 kind_completions.sort_by_key(|c| c.label.clone()); 322 kind_completions.sort_by_key(|c| c.label.clone());
331 assert_debug_snapshot_matches!(test_name, kind_completions); 323 assert_debug_snapshot_matches!(test_name, kind_completions);
332} 324}
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index a499ac7c6..53d95fb4c 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -21,10 +21,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
21 let source_root = db.file_source_root(file_id); 21 let source_root = db.file_source_root(file_id);
22 let diag = match problem { 22 let diag = match problem {
23 Problem::UnresolvedModule { candidate } => { 23 Problem::UnresolvedModule { candidate } => {
24 let create_file = FileSystemEdit::CreateFile { 24 let create_file =
25 source_root, 25 FileSystemEdit::CreateFile { source_root, path: candidate.clone() };
26 path: candidate.clone(),
27 };
28 let fix = SourceChange { 26 let fix = SourceChange {
29 label: "create module".to_string(), 27 label: "create module".to_string(),
30 source_file_edits: Vec::new(), 28 source_file_edits: Vec::new(),
@@ -44,10 +42,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
44 dst_source_root: source_root, 42 dst_source_root: source_root,
45 dst_path: move_to.clone(), 43 dst_path: move_to.clone(),
46 }; 44 };
47 let create_file = FileSystemEdit::CreateFile { 45 let create_file =
48 source_root, 46 FileSystemEdit::CreateFile { source_root, path: move_to.join(candidate) };
49 path: move_to.join(candidate),
50 };
51 let fix = SourceChange { 47 let fix = SourceChange {
52 label: "move file and create module".to_string(), 48 label: "move file and create module".to_string(),
53 source_file_edits: Vec::new(), 49 source_file_edits: Vec::new(),
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index f61feaf1b..4051728e1 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -31,9 +31,7 @@ fn extend_selection_in_macro(
31} 31}
32 32
33fn find_macro_call(node: &SyntaxNode, range: TextRange) -> Option<&ast::MacroCall> { 33fn find_macro_call(node: &SyntaxNode, range: TextRange) -> Option<&ast::MacroCall> {
34 find_covering_node(node, range) 34 find_covering_node(node, range).ancestors().find_map(ast::MacroCall::cast)
35 .ancestors()
36 .find_map(ast::MacroCall::cast)
37} 35}
38 36
39#[cfg(test)] 37#[cfg(test)]
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 69f2d2bf6..413720960 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -50,18 +50,13 @@ pub(crate) fn reference_definition(
50 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) 50 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())
51 { 51 {
52 // Check if it is a method 52 // Check if it is a method
53 if let Some(method_call) = name_ref 53 if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) {
54 .syntax()
55 .parent()
56 .and_then(ast::MethodCallExpr::cast)
57 {
58 tested_by!(goto_definition_works_for_methods); 54 tested_by!(goto_definition_works_for_methods);
59 let infer_result = function.infer(db); 55 let infer_result = function.infer(db);
60 let syntax_mapping = function.body_syntax_mapping(db); 56 let syntax_mapping = function.body_syntax_mapping(db);
61 let expr = ast::Expr::cast(method_call.syntax()).unwrap(); 57 let expr = ast::Expr::cast(method_call.syntax()).unwrap();
62 if let Some(func) = syntax_mapping 58 if let Some(func) =
63 .node_expr(expr) 59 syntax_mapping.node_expr(expr).and_then(|it| infer_result.method_resolution(it))
64 .and_then(|it| infer_result.method_resolution(it))
65 { 60 {
66 return Exact(NavigationTarget::from_function(db, func)); 61 return Exact(NavigationTarget::from_function(db, func));
67 }; 62 };
@@ -72,9 +67,8 @@ pub(crate) fn reference_definition(
72 let infer_result = function.infer(db); 67 let infer_result = function.infer(db);
73 let syntax_mapping = function.body_syntax_mapping(db); 68 let syntax_mapping = function.body_syntax_mapping(db);
74 let expr = ast::Expr::cast(field_expr.syntax()).unwrap(); 69 let expr = ast::Expr::cast(field_expr.syntax()).unwrap();
75 if let Some(field) = syntax_mapping 70 if let Some(field) =
76 .node_expr(expr) 71 syntax_mapping.node_expr(expr).and_then(|it| infer_result.field_resolution(it))
77 .and_then(|it| infer_result.field_resolution(it))
78 { 72 {
79 return Exact(NavigationTarget::from_field(db, field)); 73 return Exact(NavigationTarget::from_field(db, field));
80 }; 74 };
@@ -82,29 +76,19 @@ pub(crate) fn reference_definition(
82 } 76 }
83 // Try name resolution 77 // Try name resolution
84 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); 78 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax());
85 if let Some(path) = name_ref 79 if let Some(path) =
86 .syntax() 80 name_ref.syntax().ancestors().find_map(ast::Path::cast).and_then(hir::Path::from_ast)
87 .ancestors()
88 .find_map(ast::Path::cast)
89 .and_then(hir::Path::from_ast)
90 { 81 {
91 let resolved = resolver.resolve_path(db, &path); 82 let resolved = resolver.resolve_path(db, &path);
92 match resolved 83 match resolved.clone().take_types().or_else(|| resolved.take_values()) {
93 .clone()
94 .take_types()
95 .or_else(|| resolved.take_values())
96 {
97 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)), 84 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)),
98 Some(Resolution::LocalBinding(pat)) => { 85 Some(Resolution::LocalBinding(pat)) => {
99 let body = resolver.body().expect("no body for local binding"); 86 let body = resolver.body().expect("no body for local binding");
100 let syntax_mapping = body.syntax_mapping(db); 87 let syntax_mapping = body.syntax_mapping(db);
101 let ptr = syntax_mapping 88 let ptr =
102 .pat_syntax(pat) 89 syntax_mapping.pat_syntax(pat).expect("pattern not found in syntax mapping");
103 .expect("pattern not found in syntax mapping"); 90 let name =
104 let name = path 91 path.as_ident().cloned().expect("local binding from a multi-segment path");
105 .as_ident()
106 .cloned()
107 .expect("local binding from a multi-segment path");
108 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr); 92 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr);
109 return Exact(nav); 93 return Exact(nav);
110 } 94 }
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index f993a461c..60b81567c 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -33,13 +33,9 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
33 } 33 }
34 if range.is_none() { 34 if range.is_none() {
35 let node = find_leaf_at_offset(file.syntax(), position.offset).find_map(|leaf| { 35 let node = find_leaf_at_offset(file.syntax(), position.offset).find_map(|leaf| {
36 leaf.ancestors() 36 leaf.ancestors().find(|n| ast::Expr::cast(*n).is_some() || ast::Pat::cast(*n).is_some())
37 .find(|n| ast::Expr::cast(*n).is_some() || ast::Pat::cast(*n).is_some())
38 })?; 37 })?;
39 let frange = FileRange { 38 let frange = FileRange { file_id: position.file_id, range: node.range() };
40 file_id: position.file_id,
41 range: node.range(),
42 };
43 res.extend(type_of(db, frange).map(Into::into)); 39 res.extend(type_of(db, frange).map(Into::into));
44 range = Some(node.range()); 40 range = Some(node.range());
45 }; 41 };
@@ -126,10 +122,8 @@ impl NavigationTarget {
126 where 122 where
127 T: ast::NameOwner + ast::VisibilityOwner, 123 T: ast::NameOwner + ast::VisibilityOwner,
128 { 124 {
129 let mut string = node 125 let mut string =
130 .visibility() 126 node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default();
131 .map(|v| format!("{} ", v.syntax().text()))
132 .unwrap_or_default();
133 string.push_str(label); 127 string.push_str(label);
134 node.name()?.syntax().text().push_to(&mut string); 128 node.name()?.syntax().text().push_to(&mut string);
135 Some(string) 129 Some(string)
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index 4fb054139..444c4aeb2 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -83,9 +83,7 @@ mod tests {
83 83
84 let navs = analysis.goto_implementation(pos).unwrap().unwrap().info; 84 let navs = analysis.goto_implementation(pos).unwrap().unwrap().info;
85 assert_eq!(navs.len(), expected.len()); 85 assert_eq!(navs.len(), expected.len());
86 navs.into_iter() 86 navs.into_iter().enumerate().for_each(|(i, nav)| nav.assert_match(expected[i]));
87 .enumerate()
88 .for_each(|(i, nav)| nav.assert_match(expected[i]));
89 } 87 }
90 88
91 #[test] 89 #[test]
@@ -109,10 +107,7 @@ mod tests {
109 impl Foo {} 107 impl Foo {}
110 impl Foo {} 108 impl Foo {}
111 ", 109 ",
112 &[ 110 &["impl IMPL_BLOCK FileId(1) [12; 23)", "impl IMPL_BLOCK FileId(1) [24; 35)"],
113 "impl IMPL_BLOCK FileId(1) [12; 23)",
114 "impl IMPL_BLOCK FileId(1) [24; 35)",
115 ],
116 ); 111 );
117 } 112 }
118 113
@@ -129,10 +124,7 @@ mod tests {
129 impl super::Foo {} 124 impl super::Foo {}
130 } 125 }
131 ", 126 ",
132 &[ 127 &["impl IMPL_BLOCK FileId(1) [24; 42)", "impl IMPL_BLOCK FileId(1) [57; 75)"],
133 "impl IMPL_BLOCK FileId(1) [24; 42)",
134 "impl IMPL_BLOCK FileId(1) [57; 75)",
135 ],
136 ); 128 );
137 } 129 }
138 130
@@ -149,10 +141,7 @@ mod tests {
149 //- /b.rs 141 //- /b.rs
150 impl crate::Foo {} 142 impl crate::Foo {}
151 ", 143 ",
152 &[ 144 &["impl IMPL_BLOCK FileId(2) [0; 18)", "impl IMPL_BLOCK FileId(3) [0; 18)"],
153 "impl IMPL_BLOCK FileId(2) [0; 18)",
154 "impl IMPL_BLOCK FileId(3) [0; 18)",
155 ],
156 ); 145 );
157 } 146 }
158 147
@@ -183,10 +172,7 @@ mod tests {
183 //- /b.rs 172 //- /b.rs
184 impl crate::T for crate::Foo {} 173 impl crate::T for crate::Foo {}
185 ", 174 ",
186 &[ 175 &["impl IMPL_BLOCK FileId(2) [0; 31)", "impl IMPL_BLOCK FileId(3) [0; 31)"],
187 "impl IMPL_BLOCK FileId(2) [0; 31)",
188 "impl IMPL_BLOCK FileId(3) [0; 31)",
189 ],
190 ); 176 );
191 } 177 }
192} 178}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 1f43b7623..2d090d9b4 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -90,15 +90,8 @@ pub struct SourceFileEdit {
90 90
91#[derive(Debug)] 91#[derive(Debug)]
92pub enum FileSystemEdit { 92pub enum FileSystemEdit {
93 CreateFile { 93 CreateFile { source_root: SourceRootId, path: RelativePathBuf },
94 source_root: SourceRootId, 94 MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf },
95 path: RelativePathBuf,
96 },
97 MoveFile {
98 src: FileId,
99 dst_source_root: SourceRootId,
100 dst_path: RelativePathBuf,
101 },
102} 95}
103 96
104#[derive(Debug)] 97#[derive(Debug)]
@@ -179,9 +172,7 @@ impl AnalysisHost {
179 /// Returns a snapshot of the current state, which you can query for 172 /// Returns a snapshot of the current state, which you can query for
180 /// semantic information. 173 /// semantic information.
181 pub fn analysis(&self) -> Analysis { 174 pub fn analysis(&self) -> Analysis {
182 Analysis { 175 Analysis { db: self.db.snapshot() }
183 db: self.db.snapshot(),
184 }
185 } 176 }
186 177
187 /// Applies changes to the current state of the world. If there are 178 /// Applies changes to the current state of the world. If there are
@@ -401,17 +392,12 @@ impl Analysis {
401 392
402impl SourceChange { 393impl SourceChange {
403 pub(crate) fn from_local_edit(file_id: FileId, edit: LocalEdit) -> SourceChange { 394 pub(crate) fn from_local_edit(file_id: FileId, edit: LocalEdit) -> SourceChange {
404 let file_edit = SourceFileEdit { 395 let file_edit = SourceFileEdit { file_id, edit: edit.edit };
405 file_id,
406 edit: edit.edit,
407 };
408 SourceChange { 396 SourceChange {
409 label: edit.label, 397 label: edit.label,
410 source_file_edits: vec![file_edit], 398 source_file_edits: vec![file_edit],
411 file_system_edits: vec![], 399 file_system_edits: vec![],
412 cursor_position: edit 400 cursor_position: edit.cursor_position.map(|offset| FilePosition { offset, file_id }),
413 .cursor_position
414 .map(|offset| FilePosition { offset, file_id }),
415 } 401 }
416 } 402 }
417} 403}
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 834b30541..8d8603062 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -41,10 +41,7 @@ impl MockAnalysis {
41 let mut res = MockAnalysis::new(); 41 let mut res = MockAnalysis::new();
42 for entry in parse_fixture(fixture) { 42 for entry in parse_fixture(fixture) {
43 if entry.text.contains(CURSOR_MARKER) { 43 if entry.text.contains(CURSOR_MARKER) {
44 assert!( 44 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
45 position.is_none(),
46 "only one marker (<|>) per fixture is allowed"
47 );
48 position = Some(res.add_file_with_position(&entry.meta, &entry.text)); 45 position = Some(res.add_file_with_position(&entry.meta, &entry.text));
49 } else { 46 } else {
50 res.add_file(&entry.meta, &entry.text); 47 res.add_file(&entry.meta, &entry.text);
@@ -97,9 +94,7 @@ impl MockAnalysis {
97 let other_crate = crate_graph.add_crate_root(file_id); 94 let other_crate = crate_graph.add_crate_root(file_id);
98 let crate_name = path.parent().unwrap().file_name().unwrap(); 95 let crate_name = path.parent().unwrap().file_name().unwrap();
99 if let Some(root_crate) = root_crate { 96 if let Some(root_crate) = root_crate {
100 crate_graph 97 crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap();
101 .add_dep(root_crate, crate_name.into(), other_crate)
102 .unwrap();
103 } 98 }
104 } 99 }
105 change.add_file(source_root, file_id, path, Arc::new(contents)); 100 change.add_file(source_root, file_id, path, Arc::new(contents));
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs
index 617908aed..a2e4b6506 100644
--- a/crates/ra_ide_api/src/navigation_target.rs
+++ b/crates/ra_ide_api/src/navigation_target.rs
@@ -72,10 +72,7 @@ impl NavigationTarget {
72 72
73 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 73 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
74 let (file_id, source) = module.definition_source(db); 74 let (file_id, source) = module.definition_source(db);
75 let name = module 75 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
76 .name(db)
77 .map(|it| it.to_string().into())
78 .unwrap_or_default();
79 match source { 76 match source {
80 ModuleSource::SourceFile(node) => { 77 ModuleSource::SourceFile(node) => {
81 NavigationTarget::from_syntax(file_id, name, None, node.syntax()) 78 NavigationTarget::from_syntax(file_id, name, None, node.syntax())
@@ -87,10 +84,7 @@ impl NavigationTarget {
87 } 84 }
88 85
89 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 86 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
90 let name = module 87 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
91 .name(db)
92 .map(|it| it.to_string().into())
93 .unwrap_or_default();
94 if let Some((file_id, source)) = module.declaration_source(db) { 88 if let Some((file_id, source)) = module.declaration_source(db) {
95 return NavigationTarget::from_syntax(file_id, name, None, source.syntax()); 89 return NavigationTarget::from_syntax(file_id, name, None, source.syntax());
96 } 90 }
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index b129f3134..2cb1cc9be 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -305,9 +305,7 @@ mod tests {
305 } 305 }
306 } 306 }
307 } 307 }
308 let result = text_edit_bulder 308 let result = text_edit_bulder.finish().apply(&*analysis.file_text(file_id.unwrap()));
309 .finish()
310 .apply(&*analysis.file_text(file_id.unwrap()));
311 assert_eq_text!(expected, &*result); 309 assert_eq_text!(expected, &*result);
312 } 310 }
313} 311}
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index dc8c40ea6..d64b5a4e0 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -23,11 +23,7 @@ pub enum RunnableKind {
23 23
24pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { 24pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
25 let source_file = db.parse(file_id); 25 let source_file = db.parse(file_id);
26 source_file 26 source_file.syntax().descendants().filter_map(|i| runnable(db, file_id, i)).collect()
27 .syntax()
28 .descendants()
29 .filter_map(|i| runnable(db, file_id, i))
30 .collect()
31} 27}
32 28
33fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> { 29fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> {
@@ -45,20 +41,13 @@ fn runnable_fn(fn_def: &ast::FnDef) -> Option<Runnable> {
45 let kind = if name == "main" { 41 let kind = if name == "main" {
46 RunnableKind::Bin 42 RunnableKind::Bin
47 } else if fn_def.has_atom_attr("test") { 43 } else if fn_def.has_atom_attr("test") {
48 RunnableKind::Test { 44 RunnableKind::Test { name: name.to_string() }
49 name: name.to_string(),
50 }
51 } else if fn_def.has_atom_attr("bench") { 45 } else if fn_def.has_atom_attr("bench") {
52 RunnableKind::Bench { 46 RunnableKind::Bench { name: name.to_string() }
53 name: name.to_string(),
54 }
55 } else { 47 } else {
56 return None; 48 return None;
57 }; 49 };
58 Some(Runnable { 50 Some(Runnable { range: fn_def.syntax().range(), kind })
59 range: fn_def.syntax().range(),
60 kind,
61 })
62} 51}
63 52
64fn runnable_mod(db: &RootDatabase, file_id: FileId, module: &ast::Module) -> Option<Runnable> { 53fn runnable_mod(db: &RootDatabase, file_id: FileId, module: &ast::Module) -> Option<Runnable> {
@@ -77,16 +66,8 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: &ast::Module) -> Opt
77 let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?; 66 let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?;
78 67
79 // FIXME: thread cancellation instead of `.ok`ing 68 // FIXME: thread cancellation instead of `.ok`ing
80 let path = module 69 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
81 .path_to_root(db) 70 Some(Runnable { range, kind: RunnableKind::TestMod { path } })
82 .into_iter()
83 .rev()
84 .filter_map(|it| it.name(db))
85 .join("::");
86 Some(Runnable {
87 range,
88 kind: RunnableKind::TestMod { path },
89 })
90} 71}
91 72
92#[cfg(test)] 73#[cfg(test)]
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs
index bd355dd78..e0fc1c123 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide_api/src/status.rs
@@ -22,9 +22,7 @@ pub(crate) fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
22pub(crate) fn status(db: &RootDatabase) -> String { 22pub(crate) fn status(db: &RootDatabase) -> String {
23 let files_stats = db.query(FileTextQuery).entries::<FilesStats>(); 23 let files_stats = db.query(FileTextQuery).entries::<FilesStats>();
24 let syntax_tree_stats = syntax_tree_stats(db); 24 let syntax_tree_stats = syntax_tree_stats(db);
25 let symbols_stats = db 25 let symbols_stats = db.query(LibrarySymbolsQuery).entries::<LibrarySymbolsStats>();
26 .query(LibrarySymbolsQuery)
27 .entries::<LibrarySymbolsStats>();
28 let n_defs = { 26 let n_defs = {
29 let interner: &hir::HirInterner = db.as_ref(); 27 let interner: &hir::HirInterner = db.as_ref();
30 interner.len() 28 interner.len()
@@ -75,11 +73,7 @@ pub(crate) struct SyntaxTreeStats {
75 73
76impl fmt::Display for SyntaxTreeStats { 74impl fmt::Display for SyntaxTreeStats {
77 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 75 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
78 write!( 76 write!(fmt, "{} trees, {} ({}) retained", self.total, self.retained, self.retained_size,)
79 fmt,
80 "{} trees, {} ({}) retained",
81 self.total, self.retained, self.retained_size,
82 )
83 } 77 }
84} 78}
85 79
@@ -144,20 +138,13 @@ impl MemoryStats {
144 138
145 #[cfg(not(feature = "jemalloc"))] 139 #[cfg(not(feature = "jemalloc"))]
146 fn current() -> MemoryStats { 140 fn current() -> MemoryStats {
147 MemoryStats { 141 MemoryStats { allocated: Bytes(0), resident: Bytes(0) }
148 allocated: Bytes(0),
149 resident: Bytes(0),
150 }
151 } 142 }
152} 143}
153 144
154impl fmt::Display for MemoryStats { 145impl fmt::Display for MemoryStats {
155 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 146 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
156 write!( 147 write!(fmt, "{} allocated {} resident", self.allocated, self.resident,)
157 fmt,
158 "{} allocated {} resident",
159 self.allocated, self.resident,
160 )
161 } 148 }
162} 149}
163 150
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index 3d0b2369e..de0f46134 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -101,10 +101,7 @@ pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol>
101 } 101 }
102 102
103 let snap = Snap(db.snapshot()); 103 let snap = Snap(db.snapshot());
104 files 104 files.par_iter().map_with(snap, |db, &file_id| db.0.file_symbols(file_id)).collect()
105 .par_iter()
106 .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
107 .collect()
108 }; 105 };
109 query.search(&buf) 106 query.search(&buf)
110} 107}
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 6c4391e1e..a435fe56e 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -9,20 +9,12 @@ use crate::{
9pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { 9pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
10 let source_file = db.parse(file_id); 10 let source_file = db.parse(file_id);
11 let mut res = ra_ide_api_light::highlight(source_file.syntax()); 11 let mut res = ra_ide_api_light::highlight(source_file.syntax());
12 for macro_call in source_file 12 for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
13 .syntax()
14 .descendants()
15 .filter_map(ast::MacroCall::cast)
16 {
17 if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) { 13 if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) {
18 let mapped_ranges = ra_ide_api_light::highlight(&exp.syntax()) 14 let mapped_ranges =
19 .into_iter() 15 ra_ide_api_light::highlight(&exp.syntax()).into_iter().filter_map(|r| {
20 .filter_map(|r| {
21 let mapped_range = exp.map_range_back(r.range)?; 16 let mapped_range = exp.map_range_back(r.range)?;
22 let res = HighlightedRange { 17 let res = HighlightedRange { range: mapped_range + off, tag: r.tag };
23 range: mapped_range + off,
24 tag: r.tag,
25 };
26 Some(res) 18 Some(res)
27 }); 19 });
28 res.extend(mapped_ranges); 20 res.extend(mapped_ranges);
diff --git a/crates/ra_ide_api_light/src/diagnostics.rs b/crates/ra_ide_api_light/src/diagnostics.rs
index 2b695dfdf..7c383ca2a 100644
--- a/crates/ra_ide_api_light/src/diagnostics.rs
+++ b/crates/ra_ide_api_light/src/diagnostics.rs
@@ -72,14 +72,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
72 single_use_tree: &ast::UseTree, 72 single_use_tree: &ast::UseTree,
73) -> Option<TextEdit> { 73) -> Option<TextEdit> {
74 let use_tree_list_node = single_use_tree.syntax().parent()?; 74 let use_tree_list_node = single_use_tree.syntax().parent()?;
75 if single_use_tree 75 if single_use_tree.path()?.segment()?.syntax().first_child()?.kind() == SyntaxKind::SELF_KW {
76 .path()?
77 .segment()?
78 .syntax()
79 .first_child()?
80 .kind()
81 == SyntaxKind::SELF_KW
82 {
83 let start = use_tree_list_node.prev_sibling()?.range().start(); 76 let start = use_tree_list_node.prev_sibling()?.range().start();
84 let end = use_tree_list_node.range().end(); 77 let end = use_tree_list_node.range().end();
85 let range = TextRange::from_to(start, end); 78 let range = TextRange::from_to(start, end);
@@ -145,9 +138,8 @@ mod tests {
145 for node in file.syntax().descendants() { 138 for node in file.syntax().descendants() {
146 func(&mut diagnostics, node); 139 func(&mut diagnostics, node);
147 } 140 }
148 let diagnostic = diagnostics 141 let diagnostic =
149 .pop() 142 diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before));
150 .unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before));
151 let fix = diagnostic.fix.unwrap(); 143 let fix = diagnostic.fix.unwrap();
152 let actual = fix.edit.apply(&before); 144 let actual = fix.edit.apply(&before);
153 assert_eq_text!(after, &actual); 145 assert_eq_text!(after, &actual);
@@ -162,21 +154,9 @@ mod tests {
162 ", 154 ",
163 check_unnecessary_braces_in_use_statement, 155 check_unnecessary_braces_in_use_statement,
164 ); 156 );
165 check_apply( 157 check_apply("use {b};", "use b;", check_unnecessary_braces_in_use_statement);
166 "use {b};", 158 check_apply("use a::{c};", "use a::c;", check_unnecessary_braces_in_use_statement);
167 "use b;", 159 check_apply("use a::{self};", "use a;", check_unnecessary_braces_in_use_statement);
168 check_unnecessary_braces_in_use_statement,
169 );
170 check_apply(
171 "use a::{c};",
172 "use a::c;",
173 check_unnecessary_braces_in_use_statement,
174 );
175 check_apply(
176 "use a::{self};",
177 "use a;",
178 check_unnecessary_braces_in_use_statement,
179 );
180 check_apply( 160 check_apply(
181 "use a::{c, d::{e}};", 161 "use a::{c, d::{e}};",
182 "use a::{c, d::e};", 162 "use a::{c, d::e};",
diff --git a/crates/ra_ide_api_light/src/extend_selection.rs b/crates/ra_ide_api_light/src/extend_selection.rs
index f396dfe3f..28d62f290 100644
--- a/crates/ra_ide_api_light/src/extend_selection.rs
+++ b/crates/ra_ide_api_light/src/extend_selection.rs
@@ -43,11 +43,7 @@ pub fn extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
43 let node = find_covering_node(root, range); 43 let node = find_covering_node(root, range);
44 44
45 // Using shallowest node with same range allows us to traverse siblings. 45 // Using shallowest node with same range allows us to traverse siblings.
46 let node = node 46 let node = node.ancestors().take_while(|n| n.range() == node.range()).last().unwrap();
47 .ancestors()
48 .take_while(|n| n.range() == node.range())
49 .last()
50 .unwrap();
51 47
52 if range == node.range() { 48 if range == node.range() {
53 if string_kinds.contains(&node.kind()) { 49 if string_kinds.contains(&node.kind()) {
@@ -145,10 +141,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
145 } 141 }
146 142
147 if let Some(comma_node) = nearby_comma(node, Direction::Prev) { 143 if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
148 return Some(TextRange::from_to( 144 return Some(TextRange::from_to(comma_node.range().start(), node.range().end()));
149 comma_node.range().start(),
150 node.range().end(),
151 ));
152 } 145 }
153 146
154 if let Some(comma_node) = nearby_comma(node, Direction::Next) { 147 if let Some(comma_node) = nearby_comma(node, Direction::Next) {
@@ -160,10 +153,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
160 .filter(|node| is_single_line_ws(node)) 153 .filter(|node| is_single_line_ws(node))
161 .unwrap_or(comma_node); 154 .unwrap_or(comma_node);
162 155
163 return Some(TextRange::from_to( 156 return Some(TextRange::from_to(node.range().start(), final_node.range().end()));
164 node.range().start(),
165 final_node.range().end(),
166 ));
167 } 157 }
168 158
169 return None; 159 return None;
@@ -217,36 +207,15 @@ mod tests {
217 #[test] 207 #[test]
218 fn test_extend_selection_list() { 208 fn test_extend_selection_list() {
219 do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]); 209 do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]);
220 do_check( 210 do_check(r#"fn foo(<|>x: i32, y: i32) {}"#, &["x", "x: i32", "x: i32, "]);
221 r#"fn foo(<|>x: i32, y: i32) {}"#, 211 do_check(r#"fn foo(<|>x: i32,y: i32) {}"#, &["x", "x: i32", "x: i32,"]);
222 &["x", "x: i32", "x: i32, "], 212 do_check(r#"fn foo(x: i32, <|>y: i32) {}"#, &["y", "y: i32", ", y: i32"]);
223 ); 213 do_check(r#"fn foo(x: i32, <|>y: i32, ) {}"#, &["y", "y: i32", ", y: i32"]);
224 do_check( 214 do_check(r#"fn foo(x: i32,<|>y: i32) {}"#, &["y", "y: i32", ",y: i32"]);
225 r#"fn foo(<|>x: i32,y: i32) {}"#,
226 &["x", "x: i32", "x: i32,"],
227 );
228 do_check(
229 r#"fn foo(x: i32, <|>y: i32) {}"#,
230 &["y", "y: i32", ", y: i32"],
231 );
232 do_check(
233 r#"fn foo(x: i32, <|>y: i32, ) {}"#,
234 &["y", "y: i32", ", y: i32"],
235 );
236 do_check(
237 r#"fn foo(x: i32,<|>y: i32) {}"#,
238 &["y", "y: i32", ",y: i32"],
239 );
240 215
241 do_check( 216 do_check(r#"const FOO: [usize; 2] = [ 22<|> , 33];"#, &["22", "22 , "]);
242 r#"const FOO: [usize; 2] = [ 22<|> , 33];"#,
243 &["22", "22 , "],
244 );
245 do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]); 217 do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]);
246 do_check( 218 do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#, &["33", ", 33"]);
247 r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#,
248 &["33", ", 33"],
249 );
250 219
251 do_check( 220 do_check(
252 r#" 221 r#"
@@ -292,11 +261,7 @@ struct B {
292 <|> 261 <|>
293} 262}
294 "#, 263 "#,
295 &[ 264 &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"],
296 "\n \n",
297 "{\n \n}",
298 "/// bla\n/// bla\nstruct B {\n \n}",
299 ],
300 ) 265 )
301 } 266 }
302 267
diff --git a/crates/ra_ide_api_light/src/folding_ranges.rs b/crates/ra_ide_api_light/src/folding_ranges.rs
index c73637323..357a7dee1 100644
--- a/crates/ra_ide_api_light/src/folding_ranges.rs
+++ b/crates/ra_ide_api_light/src/folding_ranges.rs
@@ -30,30 +30,21 @@ pub fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
30 // Fold items that span multiple lines 30 // Fold items that span multiple lines
31 if let Some(kind) = fold_kind(node.kind()) { 31 if let Some(kind) = fold_kind(node.kind()) {
32 if node.text().contains('\n') { 32 if node.text().contains('\n') {
33 res.push(Fold { 33 res.push(Fold { range: node.range(), kind });
34 range: node.range(),
35 kind,
36 });
37 } 34 }
38 } 35 }
39 36
40 // Fold groups of comments 37 // Fold groups of comments
41 if node.kind() == COMMENT && !visited_comments.contains(&node) { 38 if node.kind() == COMMENT && !visited_comments.contains(&node) {
42 if let Some(range) = contiguous_range_for_comment(node, &mut visited_comments) { 39 if let Some(range) = contiguous_range_for_comment(node, &mut visited_comments) {
43 res.push(Fold { 40 res.push(Fold { range, kind: FoldKind::Comment })
44 range,
45 kind: FoldKind::Comment,
46 })
47 } 41 }
48 } 42 }
49 43
50 // Fold groups of imports 44 // Fold groups of imports
51 if node.kind() == USE_ITEM && !visited_imports.contains(&node) { 45 if node.kind() == USE_ITEM && !visited_imports.contains(&node) {
52 if let Some(range) = contiguous_range_for_group(node, &mut visited_imports) { 46 if let Some(range) = contiguous_range_for_group(node, &mut visited_imports) {
53 res.push(Fold { 47 res.push(Fold { range, kind: FoldKind::Imports })
54 range,
55 kind: FoldKind::Imports,
56 })
57 } 48 }
58 } 49 }
59 50
@@ -62,10 +53,7 @@ pub fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
62 if let Some(range) = 53 if let Some(range) =
63 contiguous_range_for_group_unless(node, has_visibility, &mut visited_mods) 54 contiguous_range_for_group_unless(node, has_visibility, &mut visited_mods)
64 { 55 {
65 res.push(Fold { 56 res.push(Fold { range, kind: FoldKind::Mods })
66 range,
67 kind: FoldKind::Mods,
68 })
69 } 57 }
70 } 58 }
71 } 59 }
@@ -84,9 +72,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
84} 72}
85 73
86fn has_visibility(node: &SyntaxNode) -> bool { 74fn has_visibility(node: &SyntaxNode) -> bool {
87 ast::Module::cast(node) 75 ast::Module::cast(node).and_then(|m| m.visibility()).is_some()
88 .and_then(|m| m.visibility())
89 .is_some()
90} 76}
91 77
92fn contiguous_range_for_group<'a>( 78fn contiguous_range_for_group<'a>(
@@ -125,10 +111,7 @@ fn contiguous_range_for_group_unless<'a>(
125 } 111 }
126 112
127 if first != last { 113 if first != last {
128 Some(TextRange::from_to( 114 Some(TextRange::from_to(first.range().start(), last.range().end()))
129 first.range().start(),
130 last.range().end(),
131 ))
132 } else { 115 } else {
133 // The group consists of only one element, therefore it cannot be folded 116 // The group consists of only one element, therefore it cannot be folded
134 None 117 None
@@ -169,10 +152,7 @@ fn contiguous_range_for_comment<'a>(
169 } 152 }
170 153
171 if first != last { 154 if first != last {
172 Some(TextRange::from_to( 155 Some(TextRange::from_to(first.range().start(), last.range().end()))
173 first.range().start(),
174 last.range().end(),
175 ))
176 } else { 156 } else {
177 // The group consists of only one element, therefore it cannot be folded 157 // The group consists of only one element, therefore it cannot be folded
178 None 158 None
@@ -199,10 +179,8 @@ mod tests {
199 fold_kinds.len(), 179 fold_kinds.len(),
200 "The amount of fold kinds is different than the expected amount" 180 "The amount of fold kinds is different than the expected amount"
201 ); 181 );
202 for ((fold, range), fold_kind) in folds 182 for ((fold, range), fold_kind) in
203 .into_iter() 183 folds.into_iter().zip(ranges.into_iter()).zip(fold_kinds.into_iter())
204 .zip(ranges.into_iter())
205 .zip(fold_kinds.into_iter())
206 { 184 {
207 assert_eq!(fold.range.start(), range.start()); 185 assert_eq!(fold.range.start(), range.start());
208 assert_eq!(fold.range.end(), range.end()); 186 assert_eq!(fold.range.end(), range.end());
@@ -280,12 +258,7 @@ mod with_attribute_next;</fold>
280fn main() <fold>{ 258fn main() <fold>{
281}</fold>"#; 259}</fold>"#;
282 260
283 let folds = &[ 261 let folds = &[FoldKind::Mods, FoldKind::Mods, FoldKind::Mods, FoldKind::Block];
284 FoldKind::Mods,
285 FoldKind::Mods,
286 FoldKind::Mods,
287 FoldKind::Block,
288 ];
289 do_check(text, folds); 262 do_check(text, folds);
290 } 263 }
291 264
diff --git a/crates/ra_ide_api_light/src/formatting.rs b/crates/ra_ide_api_light/src/formatting.rs
index 46ffa7d96..8bc03f974 100644
--- a/crates/ra_ide_api_light/src/formatting.rs
+++ b/crates/ra_ide_api_light/src/formatting.rs
@@ -32,10 +32,7 @@ fn prev_leaves(node: &SyntaxNode) -> impl Iterator<Item = &SyntaxNode> {
32} 32}
33 33
34fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> { 34fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> {
35 generate(node.ancestors().find_map(SyntaxNode::prev_sibling), |it| { 35 generate(node.ancestors().find_map(SyntaxNode::prev_sibling), |it| it.last_child()).last()
36 it.last_child()
37 })
38 .last()
39} 36}
40 37
41pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> { 38pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> {
diff --git a/crates/ra_ide_api_light/src/join_lines.rs b/crates/ra_ide_api_light/src/join_lines.rs
index ab7c5b4b5..03770c52e 100644
--- a/crates/ra_ide_api_light/src/join_lines.rs
+++ b/crates/ra_ide_api_light/src/join_lines.rs
@@ -50,11 +50,7 @@ pub fn join_lines(file: &SourceFile, range: TextRange) -> LocalEdit {
50 } 50 }
51 } 51 }
52 52
53 LocalEdit { 53 LocalEdit { label: "join lines".to_string(), edit: edit.finish(), cursor_position: None }
54 label: "join lines".to_string(),
55 edit: edit.finish(),
56 cursor_position: None,
57 }
58} 54}
59 55
60fn remove_newline( 56fn remove_newline(
@@ -71,10 +67,7 @@ fn remove_newline(
71 )]; 67 )];
72 let spaces = suff.bytes().take_while(|&b| b == b' ').count(); 68 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
73 69
74 edit.replace( 70 edit.replace(TextRange::offset_len(offset, ((spaces + 1) as u32).into()), " ".to_string());
75 TextRange::offset_len(offset, ((spaces + 1) as u32).into()),
76 " ".to_string(),
77 );
78 return; 71 return;
79 } 72 }
80 73
@@ -109,11 +102,7 @@ fn remove_newline(
109 edit.delete(TextRange::from_to(prev.range().start(), node.range().end())); 102 edit.delete(TextRange::from_to(prev.range().start(), node.range().end()));
110 } else if prev.kind() == COMMA && next.kind() == R_CURLY { 103 } else if prev.kind() == COMMA && next.kind() == R_CURLY {
111 // Removes: comma, newline (incl. surrounding whitespace) 104 // Removes: comma, newline (incl. surrounding whitespace)
112 let space = if let Some(left) = prev.prev_sibling() { 105 let space = if let Some(left) = prev.prev_sibling() { compute_ws(left, next) } else { " " };
113 compute_ws(left, next)
114 } else {
115 " "
116 };
117 edit.replace( 106 edit.replace(
118 TextRange::from_to(prev.range().start(), node.range().end()), 107 TextRange::from_to(prev.range().start(), node.range().end()),
119 space.to_string(), 108 space.to_string(),
@@ -134,20 +123,14 @@ fn join_single_expr_block(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Opti
134 let block = ast::Block::cast(node.parent()?)?; 123 let block = ast::Block::cast(node.parent()?)?;
135 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 124 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
136 let expr = extract_trivial_expression(block)?; 125 let expr = extract_trivial_expression(block)?;
137 edit.replace( 126 edit.replace(block_expr.syntax().range(), expr.syntax().text().to_string());
138 block_expr.syntax().range(),
139 expr.syntax().text().to_string(),
140 );
141 Some(()) 127 Some(())
142} 128}
143 129
144fn join_single_use_tree(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> { 130fn join_single_use_tree(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> {
145 let use_tree_list = ast::UseTreeList::cast(node.parent()?)?; 131 let use_tree_list = ast::UseTreeList::cast(node.parent()?)?;
146 let (tree,) = use_tree_list.use_trees().collect_tuple()?; 132 let (tree,) = use_tree_list.use_trees().collect_tuple()?;
147 edit.replace( 133 edit.replace(use_tree_list.syntax().range(), tree.syntax().text().to_string());
148 use_tree_list.syntax().range(),
149 tree.syntax().text().to_string(),
150 );
151 Some(()) 134 Some(())
152} 135}
153 136
diff --git a/crates/ra_ide_api_light/src/lib.rs b/crates/ra_ide_api_light/src/lib.rs
index 17044270c..f3078f51e 100644
--- a/crates/ra_ide_api_light/src/lib.rs
+++ b/crates/ra_ide_api_light/src/lib.rs
@@ -63,9 +63,8 @@ pub struct Diagnostic {
63} 63}
64 64
65pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { 65pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
66 const BRACES: &[SyntaxKind] = &[ 66 const BRACES: &[SyntaxKind] =
67 L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE, 67 &[L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE];
68 ];
69 let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax(), offset) 68 let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax(), offset)
70 .filter_map(|node| { 69 .filter_map(|node| {
71 let idx = BRACES.iter().position(|&brace| brace == node.kind())?; 70 let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
@@ -74,9 +73,7 @@ pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
74 .next()?; 73 .next()?;
75 let parent = brace_node.parent()?; 74 let parent = brace_node.parent()?;
76 let matching_kind = BRACES[brace_idx ^ 1]; 75 let matching_kind = BRACES[brace_idx ^ 1];
77 let matching_node = parent 76 let matching_node = parent.children().find(|node| node.kind() == matching_kind)?;
78 .children()
79 .find(|node| node.kind() == matching_kind)?;
80 Some(matching_node.range().start()) 77 Some(matching_node.range().start())
81} 78}
82 79
@@ -122,10 +119,7 @@ pub fn highlight(root: &SyntaxNode) -> Vec<HighlightedRange> {
122 continue; 119 continue;
123 } 120 }
124 }; 121 };
125 res.push(HighlightedRange { 122 res.push(HighlightedRange { range: node.range(), tag })
126 range: node.range(),
127 tag,
128 })
129 } 123 }
130 res 124 res
131} 125}
diff --git a/crates/ra_ide_api_light/src/line_index.rs b/crates/ra_ide_api_light/src/line_index.rs
index 131737743..bf004c33a 100644
--- a/crates/ra_ide_api_light/src/line_index.rs
+++ b/crates/ra_ide_api_light/src/line_index.rs
@@ -54,10 +54,7 @@ impl LineIndex {
54 54
55 let char_len = TextUnit::of_char(c); 55 let char_len = TextUnit::of_char(c);
56 if char_len.to_usize() > 1 { 56 if char_len.to_usize() > 1 {
57 utf16_chars.push(Utf16Char { 57 utf16_chars.push(Utf16Char { start: curr_col, end: curr_col + char_len });
58 start: curr_col,
59 end: curr_col + char_len,
60 });
61 } 58 }
62 59
63 curr_col += char_len; 60 curr_col += char_len;
@@ -68,10 +65,7 @@ impl LineIndex {
68 utf16_lines.insert(line, utf16_chars); 65 utf16_lines.insert(line, utf16_chars);
69 } 66 }
70 67
71 LineIndex { 68 LineIndex { newlines, utf16_lines }
72 newlines,
73 utf16_lines,
74 }
75 } 69 }
76 70
77 pub fn line_col(&self, offset: TextUnit) -> LineCol { 71 pub fn line_col(&self, offset: TextUnit) -> LineCol {
@@ -79,10 +73,7 @@ impl LineIndex {
79 let line_start_offset = self.newlines[line]; 73 let line_start_offset = self.newlines[line];
80 let col = offset - line_start_offset; 74 let col = offset - line_start_offset;
81 75
82 LineCol { 76 LineCol { line: line as u32, col_utf16: self.utf8_to_utf16_col(line as u32, col) as u32 }
83 line: line as u32,
84 col_utf16: self.utf8_to_utf16_col(line as u32, col) as u32,
85 }
86 } 77 }
87 78
88 pub fn offset(&self, line_col: LineCol) -> TextUnit { 79 pub fn offset(&self, line_col: LineCol) -> TextUnit {
@@ -131,10 +122,7 @@ impl LineIndex {
131#[cfg(test)] 122#[cfg(test)]
132/// Simple reference implementation to use in proptests 123/// Simple reference implementation to use in proptests
133pub fn to_line_col(text: &str, offset: TextUnit) -> LineCol { 124pub fn to_line_col(text: &str, offset: TextUnit) -> LineCol {
134 let mut res = LineCol { 125 let mut res = LineCol { line: 0, col_utf16: 0 };
135 line: 0,
136 col_utf16: 0,
137 };
138 for (i, c) in text.char_indices() { 126 for (i, c) in text.char_indices() {
139 if i + c.len_utf8() > offset.to_usize() { 127 if i + c.len_utf8() > offset.to_usize() {
140 // if it's an invalid offset, inside a multibyte char 128 // if it's an invalid offset, inside a multibyte char
@@ -161,120 +149,31 @@ mod test_line_index {
161 fn test_line_index() { 149 fn test_line_index() {
162 let text = "hello\nworld"; 150 let text = "hello\nworld";
163 let index = LineIndex::new(text); 151 let index = LineIndex::new(text);
164 assert_eq!( 152 assert_eq!(index.line_col(0.into()), LineCol { line: 0, col_utf16: 0 });
165 index.line_col(0.into()), 153 assert_eq!(index.line_col(1.into()), LineCol { line: 0, col_utf16: 1 });
166 LineCol { 154 assert_eq!(index.line_col(5.into()), LineCol { line: 0, col_utf16: 5 });
167 line: 0, 155 assert_eq!(index.line_col(6.into()), LineCol { line: 1, col_utf16: 0 });
168 col_utf16: 0 156 assert_eq!(index.line_col(7.into()), LineCol { line: 1, col_utf16: 1 });
169 } 157 assert_eq!(index.line_col(8.into()), LineCol { line: 1, col_utf16: 2 });
170 ); 158 assert_eq!(index.line_col(10.into()), LineCol { line: 1, col_utf16: 4 });
171 assert_eq!( 159 assert_eq!(index.line_col(11.into()), LineCol { line: 1, col_utf16: 5 });
172 index.line_col(1.into()), 160 assert_eq!(index.line_col(12.into()), LineCol { line: 1, col_utf16: 6 });
173 LineCol {
174 line: 0,
175 col_utf16: 1
176 }
177 );
178 assert_eq!(
179 index.line_col(5.into()),
180 LineCol {
181 line: 0,
182 col_utf16: 5
183 }
184 );
185 assert_eq!(
186 index.line_col(6.into()),
187 LineCol {
188 line: 1,
189 col_utf16: 0
190 }
191 );
192 assert_eq!(
193 index.line_col(7.into()),
194 LineCol {
195 line: 1,
196 col_utf16: 1
197 }
198 );
199 assert_eq!(
200 index.line_col(8.into()),
201 LineCol {
202 line: 1,
203 col_utf16: 2
204 }
205 );
206 assert_eq!(
207 index.line_col(10.into()),
208 LineCol {
209 line: 1,
210 col_utf16: 4
211 }
212 );
213 assert_eq!(
214 index.line_col(11.into()),
215 LineCol {
216 line: 1,
217 col_utf16: 5
218 }
219 );
220 assert_eq!(
221 index.line_col(12.into()),
222 LineCol {
223 line: 1,
224 col_utf16: 6
225 }
226 );
227 161
228 let text = "\nhello\nworld"; 162 let text = "\nhello\nworld";
229 let index = LineIndex::new(text); 163 let index = LineIndex::new(text);
230 assert_eq!( 164 assert_eq!(index.line_col(0.into()), LineCol { line: 0, col_utf16: 0 });
231 index.line_col(0.into()), 165 assert_eq!(index.line_col(1.into()), LineCol { line: 1, col_utf16: 0 });
232 LineCol { 166 assert_eq!(index.line_col(2.into()), LineCol { line: 1, col_utf16: 1 });
233 line: 0, 167 assert_eq!(index.line_col(6.into()), LineCol { line: 1, col_utf16: 5 });
234 col_utf16: 0 168 assert_eq!(index.line_col(7.into()), LineCol { line: 2, col_utf16: 0 });
235 }
236 );
237 assert_eq!(
238 index.line_col(1.into()),
239 LineCol {
240 line: 1,
241 col_utf16: 0
242 }
243 );
244 assert_eq!(
245 index.line_col(2.into()),
246 LineCol {
247 line: 1,
248 col_utf16: 1
249 }
250 );
251 assert_eq!(
252 index.line_col(6.into()),
253 LineCol {
254 line: 1,
255 col_utf16: 5
256 }
257 );
258 assert_eq!(
259 index.line_col(7.into()),
260 LineCol {
261 line: 2,
262 col_utf16: 0
263 }
264 );
265 } 169 }
266 170
267 fn arb_text_with_offset() -> BoxedStrategy<(TextUnit, String)> { 171 fn arb_text_with_offset() -> BoxedStrategy<(TextUnit, String)> {
268 arb_text() 172 arb_text().prop_flat_map(|text| (arb_offset(&text), Just(text))).boxed()
269 .prop_flat_map(|text| (arb_offset(&text), Just(text)))
270 .boxed()
271 } 173 }
272 174
273 fn to_line_col(text: &str, offset: TextUnit) -> LineCol { 175 fn to_line_col(text: &str, offset: TextUnit) -> LineCol {
274 let mut res = LineCol { 176 let mut res = LineCol { line: 0, col_utf16: 0 };
275 line: 0,
276 col_utf16: 0,
277 };
278 for (i, c) in text.char_indices() { 177 for (i, c) in text.char_indices() {
279 if i + c.len_utf8() > offset.to_usize() { 178 if i + c.len_utf8() > offset.to_usize() {
280 // if it's an invalid offset, inside a multibyte char 179 // if it's an invalid offset, inside a multibyte char
@@ -333,13 +232,7 @@ const C: char = 'メ';
333 232
334 assert_eq!(col_index.utf16_lines.len(), 1); 233 assert_eq!(col_index.utf16_lines.len(), 1);
335 assert_eq!(col_index.utf16_lines[&1].len(), 1); 234 assert_eq!(col_index.utf16_lines[&1].len(), 1);
336 assert_eq!( 235 assert_eq!(col_index.utf16_lines[&1][0], Utf16Char { start: 17.into(), end: 20.into() });
337 col_index.utf16_lines[&1][0],
338 Utf16Char {
339 start: 17.into(),
340 end: 20.into()
341 }
342 );
343 236
344 // UTF-8 to UTF-16, no changes 237 // UTF-8 to UTF-16, no changes
345 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15); 238 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15);
@@ -364,20 +257,8 @@ const C: char = \"メ メ\";
364 257
365 assert_eq!(col_index.utf16_lines.len(), 1); 258 assert_eq!(col_index.utf16_lines.len(), 1);
366 assert_eq!(col_index.utf16_lines[&1].len(), 2); 259 assert_eq!(col_index.utf16_lines[&1].len(), 2);
367 assert_eq!( 260 assert_eq!(col_index.utf16_lines[&1][0], Utf16Char { start: 17.into(), end: 20.into() });
368 col_index.utf16_lines[&1][0], 261 assert_eq!(col_index.utf16_lines[&1][1], Utf16Char { start: 21.into(), end: 24.into() });
369 Utf16Char {
370 start: 17.into(),
371 end: 20.into()
372 }
373 );
374 assert_eq!(
375 col_index.utf16_lines[&1][1],
376 Utf16Char {
377 start: 21.into(),
378 end: 24.into()
379 }
380 );
381 262
382 // UTF-8 to UTF-16 263 // UTF-8 to UTF-16
383 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15); 264 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15);
diff --git a/crates/ra_ide_api_light/src/line_index_utils.rs b/crates/ra_ide_api_light/src/line_index_utils.rs
index 5d9ab6fd2..799a920ad 100644
--- a/crates/ra_ide_api_light/src/line_index_utils.rs
+++ b/crates/ra_ide_api_light/src/line_index_utils.rs
@@ -17,11 +17,7 @@ struct LineIndexStepIter<'a> {
17 17
18impl<'a> LineIndexStepIter<'a> { 18impl<'a> LineIndexStepIter<'a> {
19 fn from(line_index: &LineIndex) -> LineIndexStepIter { 19 fn from(line_index: &LineIndex) -> LineIndexStepIter {
20 let mut x = LineIndexStepIter { 20 let mut x = LineIndexStepIter { line_index, next_newline_idx: 0, utf16_chars: None };
21 line_index,
22 next_newline_idx: 0,
23 utf16_chars: None,
24 };
25 // skip first newline since it's not real 21 // skip first newline since it's not real
26 x.next(); 22 x.next();
27 x 23 x
@@ -35,10 +31,7 @@ impl<'a> Iterator for LineIndexStepIter<'a> {
35 .as_mut() 31 .as_mut()
36 .and_then(|(newline, x)| { 32 .and_then(|(newline, x)| {
37 let x = x.next()?; 33 let x = x.next()?;
38 Some(Step::Utf16Char(TextRange::from_to( 34 Some(Step::Utf16Char(TextRange::from_to(*newline + x.start, *newline + x.end)))
39 *newline + x.start,
40 *newline + x.end,
41 )))
42 }) 35 })
43 .or_else(|| { 36 .or_else(|| {
44 let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?; 37 let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?;
@@ -113,11 +106,7 @@ struct Edits<'a> {
113 106
114impl<'a> Edits<'a> { 107impl<'a> Edits<'a> {
115 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> { 108 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> {
116 let mut x = Edits { 109 let mut x = Edits { edits: text_edit.as_atoms(), current: None, acc_diff: 0 };
117 edits: text_edit.as_atoms(),
118 current: None,
119 acc_diff: 0,
120 };
121 x.advance_edit(); 110 x.advance_edit();
122 x 111 x
123 } 112 }
@@ -127,11 +116,7 @@ impl<'a> Edits<'a> {
127 Some((next, rest)) => { 116 Some((next, rest)) => {
128 let delete = self.translate_range(next.delete); 117 let delete = self.translate_range(next.delete);
129 let diff = next.insert.len() as i64 - next.delete.len().to_usize() as i64; 118 let diff = next.insert.len() as i64 - next.delete.len().to_usize() as i64;
130 self.current = Some(TranslatedEdit { 119 self.current = Some(TranslatedEdit { delete, insert: &next.insert, diff });
131 delete,
132 insert: &next.insert,
133 diff,
134 });
135 self.edits = rest; 120 self.edits = rest;
136 } 121 }
137 None => { 122 None => {
@@ -142,10 +127,7 @@ impl<'a> Edits<'a> {
142 127
143 fn next_inserted_steps(&mut self) -> Option<OffsetStepIter<'a>> { 128 fn next_inserted_steps(&mut self) -> Option<OffsetStepIter<'a>> {
144 let cur = self.current.as_ref()?; 129 let cur = self.current.as_ref()?;
145 let res = Some(OffsetStepIter { 130 let res = Some(OffsetStepIter { offset: cur.delete.start(), text: &cur.insert });
146 offset: cur.delete.start(),
147 text: &cur.insert,
148 });
149 self.advance_edit(); 131 self.advance_edit();
150 res 132 res
151 } 133 }
@@ -160,18 +142,12 @@ impl<'a> Edits<'a> {
160 if step_pos <= edit.delete.start() { 142 if step_pos <= edit.delete.start() {
161 NextSteps::Use 143 NextSteps::Use
162 } else if step_pos <= edit.delete.end() { 144 } else if step_pos <= edit.delete.end() {
163 let iter = OffsetStepIter { 145 let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert };
164 offset: edit.delete.start(),
165 text: &edit.insert,
166 };
167 // empty slice to avoid returning steps again 146 // empty slice to avoid returning steps again
168 edit.insert = &edit.insert[edit.insert.len()..]; 147 edit.insert = &edit.insert[edit.insert.len()..];
169 NextSteps::ReplaceMany(iter) 148 NextSteps::ReplaceMany(iter)
170 } else { 149 } else {
171 let iter = OffsetStepIter { 150 let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert };
172 offset: edit.delete.start(),
173 text: &edit.insert,
174 };
175 // empty slice to avoid returning steps again 151 // empty slice to avoid returning steps again
176 edit.insert = &edit.insert[edit.insert.len()..]; 152 edit.insert = &edit.insert[edit.insert.len()..];
177 self.advance_edit(); 153 self.advance_edit();
@@ -222,11 +198,7 @@ struct RunningLineCol {
222 198
223impl RunningLineCol { 199impl RunningLineCol {
224 fn new() -> RunningLineCol { 200 fn new() -> RunningLineCol {
225 RunningLineCol { 201 RunningLineCol { line: 0, last_newline: TextUnit::from(0), col_adjust: TextUnit::from(0) }
226 line: 0,
227 last_newline: TextUnit::from(0),
228 col_adjust: TextUnit::from(0),
229 }
230 } 202 }
231 203
232 fn to_line_col(&self, offset: TextUnit) -> LineCol { 204 fn to_line_col(&self, offset: TextUnit) -> LineCol {
@@ -339,12 +311,7 @@ mod test {
339 let edited_text = x.edit.apply(&x.text); 311 let edited_text = x.edit.apply(&x.text);
340 let arb_offset = arb_offset(&edited_text); 312 let arb_offset = arb_offset(&edited_text);
341 (Just(x), Just(edited_text), arb_offset).prop_map(|(x, edited_text, offset)| { 313 (Just(x), Just(edited_text), arb_offset).prop_map(|(x, edited_text, offset)| {
342 ArbTextWithEditAndOffset { 314 ArbTextWithEditAndOffset { text: x.text, edit: x.edit, edited_text, offset }
343 text: x.text,
344 edit: x.edit,
345 edited_text,
346 offset,
347 }
348 }) 315 })
349 }) 316 })
350 .boxed() 317 .boxed()
diff --git a/crates/ra_ide_api_light/src/structure.rs b/crates/ra_ide_api_light/src/structure.rs
index 330a3694c..75afd1181 100644
--- a/crates/ra_ide_api_light/src/structure.rs
+++ b/crates/ra_ide_api_light/src/structure.rs
@@ -70,10 +70,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
70 node_range: node.syntax().range(), 70 node_range: node.syntax().range(),
71 kind: node.syntax().kind(), 71 kind: node.syntax().kind(),
72 detail, 72 detail,
73 deprecated: node 73 deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
74 .attrs()
75 .filter_map(|x| x.as_named())
76 .any(|x| x == "deprecated"),
77 }) 74 })
78 } 75 }
79 76
@@ -123,11 +120,9 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
123 let target_trait = im.target_trait(); 120 let target_trait = im.target_trait();
124 let label = match target_trait { 121 let label = match target_trait {
125 None => format!("impl {}", target_type.syntax().text()), 122 None => format!("impl {}", target_type.syntax().text()),
126 Some(t) => format!( 123 Some(t) => {
127 "impl {} for {}", 124 format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
128 t.syntax().text(), 125 }
129 target_type.syntax().text(),
130 ),
131 }; 126 };
132 127
133 let node = StructureNode { 128 let node = StructureNode {
diff --git a/crates/ra_ide_api_light/src/typing.rs b/crates/ra_ide_api_light/src/typing.rs
index 861027b9f..a08a5a8c5 100644
--- a/crates/ra_ide_api_light/src/typing.rs
+++ b/crates/ra_ide_api_light/src/typing.rs
@@ -8,9 +8,8 @@ use ra_syntax::{
8use crate::{LocalEdit, TextEditBuilder, formatting::leading_indent}; 8use crate::{LocalEdit, TextEditBuilder, formatting::leading_indent};
9 9
10pub fn on_enter(file: &SourceFile, offset: TextUnit) -> Option<LocalEdit> { 10pub fn on_enter(file: &SourceFile, offset: TextUnit) -> Option<LocalEdit> {
11 let comment = find_leaf_at_offset(file.syntax(), offset) 11 let comment =
12 .left_biased() 12 find_leaf_at_offset(file.syntax(), offset).left_biased().and_then(ast::Comment::cast)?;
13 .and_then(ast::Comment::cast)?;
14 13
15 if let ast::CommentFlavor::Multiline = comment.flavor() { 14 if let ast::CommentFlavor::Multiline = comment.flavor() {
16 return None; 15 return None;
@@ -64,12 +63,7 @@ pub fn on_eq_typed(file: &SourceFile, eq_offset: TextUnit) -> Option<LocalEdit>
64 if expr_range.contains(eq_offset) && eq_offset != expr_range.start() { 63 if expr_range.contains(eq_offset) && eq_offset != expr_range.start() {
65 return None; 64 return None;
66 } 65 }
67 if file 66 if file.syntax().text().slice(eq_offset..expr_range.start()).contains('\n') {
68 .syntax()
69 .text()
70 .slice(eq_offset..expr_range.start())
71 .contains('\n')
72 {
73 return None; 67 return None;
74 } 68 }
75 } else { 69 } else {
@@ -100,10 +94,7 @@ pub fn on_dot_typed(file: &SourceFile, dot_offset: TextUnit) -> Option<LocalEdit
100 let current_indent_len = TextUnit::of_str(current_indent); 94 let current_indent_len = TextUnit::of_str(current_indent);
101 95
102 // Make sure dot is a part of call chain 96 // Make sure dot is a part of call chain
103 let field_expr = whitespace 97 let field_expr = whitespace.syntax().parent().and_then(ast::FieldExpr::cast)?;
104 .syntax()
105 .parent()
106 .and_then(ast::FieldExpr::cast)?;
107 let prev_indent = leading_indent(field_expr.syntax())?; 98 let prev_indent = leading_indent(field_expr.syntax())?;
108 let target_indent = format!(" {}", prev_indent); 99 let target_indent = format!(" {}", prev_indent);
109 let target_indent_len = TextUnit::of_str(&target_indent); 100 let target_indent_len = TextUnit::of_str(&target_indent);
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index 39992788d..2af2b89fe 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -7,15 +7,13 @@ use lsp_types::{
7 7
8pub fn server_capabilities() -> ServerCapabilities { 8pub fn server_capabilities() -> ServerCapabilities {
9 ServerCapabilities { 9 ServerCapabilities {
10 text_document_sync: Some(TextDocumentSyncCapability::Options( 10 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
11 TextDocumentSyncOptions { 11 open_close: Some(true),
12 open_close: Some(true), 12 change: Some(TextDocumentSyncKind::Full),
13 change: Some(TextDocumentSyncKind::Full), 13 will_save: None,
14 will_save: None, 14 will_save_wait_until: None,
15 will_save_wait_until: None, 15 save: None,
16 save: None, 16 })),
17 },
18 )),
19 hover_provider: Some(true), 17 hover_provider: Some(true),
20 completion_provider: Some(CompletionOptions { 18 completion_provider: Some(CompletionOptions {
21 resolve_provider: None, 19 resolve_provider: None,
@@ -32,9 +30,7 @@ pub fn server_capabilities() -> ServerCapabilities {
32 document_symbol_provider: Some(true), 30 document_symbol_provider: Some(true),
33 workspace_symbol_provider: Some(true), 31 workspace_symbol_provider: Some(true),
34 code_action_provider: Some(CodeActionProviderCapability::Simple(true)), 32 code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
35 code_lens_provider: Some(CodeLensOptions { 33 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
36 resolve_provider: Some(true),
37 }),
38 document_formatting_provider: Some(true), 34 document_formatting_provider: Some(true),
39 document_range_formatting_provider: None, 35 document_range_formatting_provider: None,
40 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { 36 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs
index db9496bbe..e011eab7c 100644
--- a/crates/ra_lsp_server/src/cargo_target_spec.rs
+++ b/crates/ra_lsp_server/src/cargo_target_spec.rs
@@ -64,10 +64,7 @@ impl CargoTargetSpec {
64 None => return Ok(None), 64 None => return Ok(None),
65 }; 65 };
66 let file_id = world.analysis().crate_root(crate_id)?; 66 let file_id = world.analysis().crate_root(crate_id)?;
67 let path = world 67 let path = world.vfs.read().file2path(ra_vfs::VfsFile(file_id.0.into()));
68 .vfs
69 .read()
70 .file2path(ra_vfs::VfsFile(file_id.0.into()));
71 let res = world.workspaces.iter().find_map(|ws| { 68 let res = world.workspaces.iter().find_map(|ws| {
72 let tgt = ws.cargo.target_by_root(&path)?; 69 let tgt = ws.cargo.target_by_root(&path)?;
73 let res = CargoTargetSpec { 70 let res = CargoTargetSpec {
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 981385466..20077a48a 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -82,11 +82,8 @@ impl ConvWith for CompletionItem {
82 fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem { 82 fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem {
83 let atom_text_edit = AtomTextEdit::replace(self.source_range(), self.insert_text()); 83 let atom_text_edit = AtomTextEdit::replace(self.source_range(), self.insert_text());
84 let text_edit = (&atom_text_edit).conv_with(ctx); 84 let text_edit = (&atom_text_edit).conv_with(ctx);
85 let additional_text_edits = if let Some(edit) = self.take_text_edit() { 85 let additional_text_edits =
86 Some(edit.conv_with(ctx)) 86 if let Some(edit) = self.take_text_edit() { Some(edit.conv_with(ctx)) } else { None };
87 } else {
88 None
89 };
90 87
91 let mut res = lsp_types::CompletionItem { 88 let mut res = lsp_types::CompletionItem {
92 label: self.label().to_string(), 89 label: self.label().to_string(),
@@ -112,10 +109,7 @@ impl ConvWith for Position {
112 type Output = TextUnit; 109 type Output = TextUnit;
113 110
114 fn conv_with(self, line_index: &LineIndex) -> TextUnit { 111 fn conv_with(self, line_index: &LineIndex) -> TextUnit {
115 let line_col = LineCol { 112 let line_col = LineCol { line: self.line as u32, col_utf16: self.character as u32 };
116 line: self.line as u32,
117 col_utf16: self.character as u32,
118 };
119 line_index.offset(line_col) 113 line_index.offset(line_col)
120 } 114 }
121} 115}
@@ -135,10 +129,7 @@ impl ConvWith for TextRange {
135 type Output = Range; 129 type Output = Range;
136 130
137 fn conv_with(self, line_index: &LineIndex) -> Range { 131 fn conv_with(self, line_index: &LineIndex) -> Range {
138 Range::new( 132 Range::new(self.start().conv_with(line_index), self.end().conv_with(line_index))
139 self.start().conv_with(line_index),
140 self.end().conv_with(line_index),
141 )
142 } 133 }
143} 134}
144 135
@@ -147,10 +138,7 @@ impl ConvWith for Range {
147 type Output = TextRange; 138 type Output = TextRange;
148 139
149 fn conv_with(self, line_index: &LineIndex) -> TextRange { 140 fn conv_with(self, line_index: &LineIndex) -> TextRange {
150 TextRange::from_to( 141 TextRange::from_to(self.start.conv_with(line_index), self.end.conv_with(line_index))
151 self.start.conv_with(line_index),
152 self.end.conv_with(line_index),
153 )
154 } 142 }
155} 143}
156 144
@@ -303,11 +291,7 @@ impl TryConvWith for SourceChange {
303 changes: None, 291 changes: None,
304 document_changes: Some(DocumentChanges::Operations(document_changes)), 292 document_changes: Some(DocumentChanges::Operations(document_changes)),
305 }; 293 };
306 Ok(req::SourceChange { 294 Ok(req::SourceChange { label: self.label, workspace_edit, cursor_position })
307 label: self.label,
308 workspace_edit,
309 cursor_position,
310 })
311 } 295 }
312} 296}
313 297
@@ -320,16 +304,8 @@ impl TryConvWith for SourceFileEdit {
320 version: None, 304 version: None,
321 }; 305 };
322 let line_index = world.analysis().file_line_index(self.file_id); 306 let line_index = world.analysis().file_line_index(self.file_id);
323 let edits = self 307 let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect();
324 .edit 308 Ok(TextDocumentEdit { text_document, edits })
325 .as_atoms()
326 .iter()
327 .map_conv_with(&line_index)
328 .collect();
329 Ok(TextDocumentEdit {
330 text_document,
331 edits,
332 })
333 } 309 }
334} 310}
335 311
@@ -342,18 +318,10 @@ impl TryConvWith for FileSystemEdit {
342 let uri = world.path_to_uri(source_root, &path)?; 318 let uri = world.path_to_uri(source_root, &path)?;
343 ResourceOp::Create(CreateFile { uri, options: None }) 319 ResourceOp::Create(CreateFile { uri, options: None })
344 } 320 }
345 FileSystemEdit::MoveFile { 321 FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => {
346 src,
347 dst_source_root,
348 dst_path,
349 } => {
350 let old_uri = world.file_id_to_uri(src)?; 322 let old_uri = world.file_id_to_uri(src)?;
351 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?; 323 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?;
352 ResourceOp::Rename(RenameFile { 324 ResourceOp::Rename(RenameFile { old_uri, new_uri, options: None })
353 old_uri,
354 new_uri,
355 options: None,
356 })
357 } 325 }
358 }; 326 };
359 Ok(res) 327 Ok(res)
@@ -381,11 +349,8 @@ pub fn to_location_link(
381 349
382 let target_range = target.info.full_range().conv_with(&tgt_line_index); 350 let target_range = target.info.full_range().conv_with(&tgt_line_index);
383 351
384 let target_selection_range = target 352 let target_selection_range =
385 .info 353 target.info.focus_range().map(|it| it.conv_with(&tgt_line_index)).unwrap_or(target_range);
386 .focus_range()
387 .map(|it| it.conv_with(&tgt_line_index))
388 .unwrap_or(target_range);
389 354
390 let res = LocationLink { 355 let res = LocationLink {
391 origin_selection_range: Some(target.range.conv_with(line_index)), 356 origin_selection_range: Some(target.range.conv_with(line_index)),
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index 33aa30d70..03f83c7be 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -36,23 +36,15 @@ struct InitializationOptions {
36fn main_inner() -> Result<()> { 36fn main_inner() -> Result<()> {
37 let (receiver, sender, threads) = stdio_transport(); 37 let (receiver, sender, threads) = stdio_transport();
38 let cwd = ::std::env::current_dir()?; 38 let cwd = ::std::env::current_dir()?;
39 run_server( 39 run_server(ra_lsp_server::server_capabilities(), receiver, sender, |params, r, s| {
40 ra_lsp_server::server_capabilities(), 40 let root = params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd);
41 receiver, 41 let supports_decorations = params
42 sender, 42 .initialization_options
43 |params, r, s| { 43 .and_then(|v| InitializationOptions::deserialize(v).ok())
44 let root = params 44 .and_then(|it| it.publish_decorations)
45 .root_uri 45 == Some(true);
46 .and_then(|it| it.to_file_path().ok()) 46 ra_lsp_server::main_loop(false, root, supports_decorations, r, s)
47 .unwrap_or(cwd); 47 })?;
48 let supports_decorations = params
49 .initialization_options
50 .and_then(|v| InitializationOptions::deserialize(v).ok())
51 .and_then(|it| it.publish_decorations)
52 == Some(true);
53 ra_lsp_server::main_loop(false, root, supports_decorations, r, s)
54 },
55 )?;
56 log::info!("shutting down IO..."); 48 log::info!("shutting down IO...");
57 threads.join()?; 49 threads.join()?;
58 log::info!("... IO is down"); 50 log::info!("... IO is down");
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 26b6fe54a..a51299851 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -25,10 +25,7 @@ use crate::{
25}; 25};
26 26
27#[derive(Debug, Fail)] 27#[derive(Debug, Fail)]
28#[fail( 28#[fail(display = "Language Server request failed with {}. ({})", code, message)]
29 display = "Language Server request failed with {}. ({})",
30 code, message
31)]
32pub struct LspError { 29pub struct LspError {
33 pub code: i32, 30 pub code: i32,
34 pub message: String, 31 pub message: String,
@@ -69,9 +66,7 @@ pub fn main_loop(
69 } 66 }
70 }; 67 };
71 ws_worker.shutdown(); 68 ws_worker.shutdown();
72 ws_watcher 69 ws_watcher.shutdown().map_err(|_| format_err!("ws watcher died"))?;
73 .shutdown()
74 .map_err(|_| format_err!("ws watcher died"))?;
75 let mut state = ServerWorldState::new(ws_root.clone(), workspaces); 70 let mut state = ServerWorldState::new(ws_root.clone(), workspaces);
76 71
77 log::info!("server initialized, serving requests"); 72 log::info!("server initialized, serving requests");
@@ -92,9 +87,7 @@ pub fn main_loop(
92 ); 87 );
93 88
94 log::info!("waiting for tasks to finish..."); 89 log::info!("waiting for tasks to finish...");
95 task_receiver 90 task_receiver.into_iter().for_each(|task| on_task(task, msg_sender, &mut pending_requests));
96 .into_iter()
97 .for_each(|task| on_task(task, msg_sender, &mut pending_requests));
98 log::info!("...tasks have finished"); 91 log::info!("...tasks have finished");
99 log::info!("joining threadpool..."); 92 log::info!("joining threadpool...");
100 drop(pool); 93 drop(pool);
@@ -119,9 +112,7 @@ enum Event {
119impl fmt::Debug for Event { 112impl fmt::Debug for Event {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 let debug_verbose_not = |not: &RawNotification, f: &mut fmt::Formatter| { 114 let debug_verbose_not = |not: &RawNotification, f: &mut fmt::Formatter| {
122 f.debug_struct("RawNotification") 115 f.debug_struct("RawNotification").field("method", &not.method).finish()
123 .field("method", &not.method)
124 .finish()
125 }; 116 };
126 117
127 match self { 118 match self {
@@ -287,13 +278,7 @@ fn on_request(
287 sender: &Sender<Task>, 278 sender: &Sender<Task>,
288 req: RawRequest, 279 req: RawRequest,
289) -> Result<Option<RawRequest>> { 280) -> Result<Option<RawRequest>> {
290 let mut pool_dispatcher = PoolDispatcher { 281 let mut pool_dispatcher = PoolDispatcher { req: Some(req), res: None, pool, world, sender };
291 req: Some(req),
292 res: None,
293 pool,
294 world,
295 sender,
296 };
297 let req = pool_dispatcher 282 let req = pool_dispatcher
298 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)? 283 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)?
299 .on::<req::SyntaxTree>(handlers::handle_syntax_tree)? 284 .on::<req::SyntaxTree>(handlers::handle_syntax_tree)?
@@ -362,13 +347,9 @@ fn on_notification(
362 let not = match not.cast::<req::DidOpenTextDocument>() { 347 let not = match not.cast::<req::DidOpenTextDocument>() {
363 Ok(params) => { 348 Ok(params) => {
364 let uri = params.text_document.uri; 349 let uri = params.text_document.uri;
365 let path = uri 350 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
366 .to_file_path() 351 if let Some(file_id) =
367 .map_err(|()| format_err!("invalid uri: {}", uri))?; 352 state.vfs.write().add_file_overlay(&path, params.text_document.text)
368 if let Some(file_id) = state
369 .vfs
370 .write()
371 .add_file_overlay(&path, params.text_document.text)
372 { 353 {
373 subs.add_sub(FileId(file_id.0.into())); 354 subs.add_sub(FileId(file_id.0.into()));
374 } 355 }
@@ -379,14 +360,9 @@ fn on_notification(
379 let not = match not.cast::<req::DidChangeTextDocument>() { 360 let not = match not.cast::<req::DidChangeTextDocument>() {
380 Ok(mut params) => { 361 Ok(mut params) => {
381 let uri = params.text_document.uri; 362 let uri = params.text_document.uri;
382 let path = uri 363 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
383 .to_file_path() 364 let text =
384 .map_err(|()| format_err!("invalid uri: {}", uri))?; 365 params.content_changes.pop().ok_or_else(|| format_err!("empty changes"))?.text;
385 let text = params
386 .content_changes
387 .pop()
388 .ok_or_else(|| format_err!("empty changes"))?
389 .text;
390 state.vfs.write().change_file_overlay(path.as_path(), text); 366 state.vfs.write().change_file_overlay(path.as_path(), text);
391 return Ok(()); 367 return Ok(());
392 } 368 }
@@ -395,16 +371,11 @@ fn on_notification(
395 let not = match not.cast::<req::DidCloseTextDocument>() { 371 let not = match not.cast::<req::DidCloseTextDocument>() {
396 Ok(params) => { 372 Ok(params) => {
397 let uri = params.text_document.uri; 373 let uri = params.text_document.uri;
398 let path = uri 374 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
399 .to_file_path()
400 .map_err(|()| format_err!("invalid uri: {}", uri))?;
401 if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { 375 if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) {
402 subs.remove_sub(FileId(file_id.0.into())); 376 subs.remove_sub(FileId(file_id.0.into()));
403 } 377 }
404 let params = req::PublishDiagnosticsParams { 378 let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() };
405 uri,
406 diagnostics: Vec::new(),
407 };
408 let not = RawNotification::new::<req::PublishDiagnostics>(&params); 379 let not = RawNotification::new::<req::PublishDiagnostics>(&params);
409 msg_sender.send(RawMessage::Notification(not)).unwrap(); 380 msg_sender.send(RawMessage::Notification(not)).unwrap();
410 return Ok(()); 381 return Ok(());
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index aa55d1255..0cdb39c32 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -46,12 +46,7 @@ pub fn handle_extend_selection(
46 .into_iter() 46 .into_iter()
47 .map_conv_with(&line_index) 47 .map_conv_with(&line_index)
48 .map(|range| FileRange { file_id, range }) 48 .map(|range| FileRange { file_id, range })
49 .map(|frange| { 49 .map(|frange| world.analysis().extend_selection(frange).map(|it| it.conv_with(&line_index)))
50 world
51 .analysis()
52 .extend_selection(frange)
53 .map(|it| it.conv_with(&line_index))
54 })
55 .collect::<Cancelable<Vec<_>>>()?; 50 .collect::<Cancelable<Vec<_>>>()?;
56 Ok(req::ExtendSelectionResult { selections }) 51 Ok(req::ExtendSelectionResult { selections })
57} 52}
@@ -67,10 +62,7 @@ pub fn handle_find_matching_brace(
67 .into_iter() 62 .into_iter()
68 .map_conv_with(&line_index) 63 .map_conv_with(&line_index)
69 .map(|offset| { 64 .map(|offset| {
70 world 65 world.analysis().matching_brace(FilePosition { file_id, offset }).unwrap_or(offset)
71 .analysis()
72 .matching_brace(FilePosition { file_id, offset })
73 .unwrap_or(offset)
74 }) 66 })
75 .map_conv_with(&line_index) 67 .map_conv_with(&line_index)
76 .collect(); 68 .collect();
@@ -171,11 +163,7 @@ pub fn handle_workspace_symbol(
171 let all_symbols = params.query.contains('#'); 163 let all_symbols = params.query.contains('#');
172 let libs = params.query.contains('*'); 164 let libs = params.query.contains('*');
173 let query = { 165 let query = {
174 let query: String = params 166 let query: String = params.query.chars().filter(|&c| c != '#' && c != '*').collect();
175 .query
176 .chars()
177 .filter(|&c| c != '#' && c != '*')
178 .collect();
179 let mut q = Query::new(query); 167 let mut q = Query::new(query);
180 if !all_symbols { 168 if !all_symbols {
181 q.only_types(); 169 q.only_types();
@@ -367,10 +355,7 @@ pub fn handle_completion(
367 Some(items) => items, 355 Some(items) => items,
368 }; 356 };
369 let line_index = world.analysis().file_line_index(position.file_id); 357 let line_index = world.analysis().file_line_index(position.file_id);
370 let items = items 358 let items = items.into_iter().map(|item| item.conv_with(&line_index)).collect();
371 .into_iter()
372 .map(|item| item.conv_with(&line_index))
373 .collect();
374 359
375 Ok(Some(req::CompletionResponse::Array(items))) 360 Ok(Some(req::CompletionResponse::Array(items)))
376} 361}
@@ -496,9 +481,8 @@ pub fn handle_rename(world: ServerWorld, params: RenameParams) -> Result<Option<
496 .into()); 481 .into());
497 } 482 }
498 483
499 let optional_change = world 484 let optional_change =
500 .analysis() 485 world.analysis().rename(FilePosition { file_id, offset }, &*params.new_name)?;
501 .rename(FilePosition { file_id, offset }, &*params.new_name)?;
502 let change = match optional_change { 486 let change = match optional_change {
503 None => return Ok(None), 487 None => return Ok(None),
504 Some(it) => it, 488 Some(it) => it,
@@ -517,14 +501,10 @@ pub fn handle_references(
517 let line_index = world.analysis().file_line_index(file_id); 501 let line_index = world.analysis().file_line_index(file_id);
518 let offset = params.position.conv_with(&line_index); 502 let offset = params.position.conv_with(&line_index);
519 503
520 let refs = world 504 let refs = world.analysis().find_all_refs(FilePosition { file_id, offset })?;
521 .analysis()
522 .find_all_refs(FilePosition { file_id, offset })?;
523 505
524 Ok(Some( 506 Ok(Some(
525 refs.into_iter() 507 refs.into_iter().filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()).collect(),
526 .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok())
527 .collect(),
528 )) 508 ))
529} 509}
530 510
@@ -540,9 +520,7 @@ pub fn handle_formatting(
540 520
541 use std::process; 521 use std::process;
542 let mut rustfmt = process::Command::new("rustfmt"); 522 let mut rustfmt = process::Command::new("rustfmt");
543 rustfmt 523 rustfmt.stdin(process::Stdio::piped()).stdout(process::Stdio::piped());
544 .stdin(process::Stdio::piped())
545 .stdout(process::Stdio::piped());
546 524
547 if let Ok(path) = params.text_document.uri.to_file_path() { 525 if let Ok(path) = params.text_document.uri.to_file_path() {
548 if let Some(parent) = path.parent() { 526 if let Some(parent) = path.parent() {
@@ -582,10 +560,7 @@ pub fn handle_code_action(
582 let line_index = world.analysis().file_line_index(file_id); 560 let line_index = world.analysis().file_line_index(file_id);
583 let range = params.range.conv_with(&line_index); 561 let range = params.range.conv_with(&line_index);
584 562
585 let assists = world 563 let assists = world.analysis().assists(FileRange { file_id, range })?.into_iter();
586 .analysis()
587 .assists(FileRange { file_id, range })?
588 .into_iter();
589 let fixes = world 564 let fixes = world
590 .analysis() 565 .analysis()
591 .diagnostics(file_id)? 566 .diagnostics(file_id)?
@@ -720,18 +695,11 @@ pub fn handle_code_lens_resolve(world: ServerWorld, code_lens: CodeLens) -> Resu
720 to_value(locations).unwrap(), 695 to_value(locations).unwrap(),
721 ]), 696 ]),
722 }; 697 };
723 Ok(CodeLens { 698 Ok(CodeLens { range: code_lens.range, command: Some(cmd), data: None })
724 range: code_lens.range,
725 command: Some(cmd),
726 data: None,
727 })
728 } 699 }
729 None => Ok(CodeLens { 700 None => Ok(CodeLens {
730 range: code_lens.range, 701 range: code_lens.range,
731 command: Some(Command { 702 command: Some(Command { title: "Error".into(), ..Default::default() }),
732 title: "Error".into(),
733 ..Default::default()
734 }),
735 data: None, 703 data: None,
736 }), 704 }),
737 } 705 }
@@ -744,16 +712,11 @@ pub fn handle_document_highlight(
744 let file_id = params.text_document.try_conv_with(&world)?; 712 let file_id = params.text_document.try_conv_with(&world)?;
745 let line_index = world.analysis().file_line_index(file_id); 713 let line_index = world.analysis().file_line_index(file_id);
746 714
747 let refs = world 715 let refs = world.analysis().find_all_refs(params.try_conv_with(&world)?)?;
748 .analysis()
749 .find_all_refs(params.try_conv_with(&world)?)?;
750 716
751 Ok(Some( 717 Ok(Some(
752 refs.into_iter() 718 refs.into_iter()
753 .map(|r| DocumentHighlight { 719 .map(|r| DocumentHighlight { range: r.1.conv_with(&line_index), kind: None })
754 range: r.1.conv_with(&line_index),
755 kind: None,
756 })
757 .collect(), 720 .collect(),
758 )) 721 ))
759} 722}
@@ -785,10 +748,7 @@ pub fn publish_decorations(
785 file_id: FileId, 748 file_id: FileId,
786) -> Result<req::PublishDecorationsParams> { 749) -> Result<req::PublishDecorationsParams> {
787 let uri = world.file_id_to_uri(file_id)?; 750 let uri = world.file_id_to_uri(file_id)?;
788 Ok(req::PublishDecorationsParams { 751 Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? })
789 uri,
790 decorations: highlight(&world, file_id)?,
791 })
792} 752}
793 753
794fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> { 754fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> {
@@ -797,10 +757,7 @@ fn highlight(world: &ServerWorld, file_id: FileId) -> Result<Vec<Decoration>> {
797 .analysis() 757 .analysis()
798 .highlight(file_id)? 758 .highlight(file_id)?
799 .into_iter() 759 .into_iter()
800 .map(|h| Decoration { 760 .map(|h| Decoration { range: h.range.conv_with(&line_index), tag: h.tag })
801 range: h.range.conv_with(&line_index),
802 tag: h.tag,
803 })
804 .collect(); 761 .collect();
805 Ok(res) 762 Ok(res)
806} 763}
diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
index a83e01557..11bd952d9 100644
--- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs
+++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
@@ -7,9 +7,7 @@ pub struct Subscriptions {
7 7
8impl Subscriptions { 8impl Subscriptions {
9 pub fn new() -> Subscriptions { 9 pub fn new() -> Subscriptions {
10 Subscriptions { 10 Subscriptions { subs: FxHashSet::default() }
11 subs: FxHashSet::default(),
12 }
13 } 11 }
14 pub fn add_sub(&mut self, file_id: FileId) { 12 pub fn add_sub(&mut self, file_id: FileId) {
15 self.subs.insert(file_id); 13 self.subs.insert(file_id);
diff --git a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs b/crates/ra_lsp_server/src/project_model/cargo_workspace.rs
index 8cf99d586..3b76389d2 100644
--- a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs
+++ b/crates/ra_lsp_server/src/project_model/cargo_workspace.rs
@@ -118,14 +118,11 @@ impl Target {
118impl CargoWorkspace { 118impl CargoWorkspace {
119 pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> { 119 pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> {
120 let mut meta = MetadataCommand::new(); 120 let mut meta = MetadataCommand::new();
121 meta.manifest_path(cargo_toml) 121 meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures);
122 .features(CargoOpt::AllFeatures);
123 if let Some(parent) = cargo_toml.parent() { 122 if let Some(parent) = cargo_toml.parent() {
124 meta.current_dir(parent); 123 meta.current_dir(parent);
125 } 124 }
126 let meta = meta 125 let meta = meta.exec().map_err(|e| format_err!("cargo metadata failed: {}", e))?;
127 .exec()
128 .map_err(|e| format_err!("cargo metadata failed: {}", e))?;
129 let mut pkg_by_id = FxHashMap::default(); 126 let mut pkg_by_id = FxHashMap::default();
130 let mut packages = Arena::default(); 127 let mut packages = Arena::default();
131 let mut targets = Arena::default(); 128 let mut targets = Arena::default();
@@ -157,10 +154,8 @@ impl CargoWorkspace {
157 for node in resolve.nodes { 154 for node in resolve.nodes {
158 let source = pkg_by_id[&node.id]; 155 let source = pkg_by_id[&node.id];
159 for dep_node in node.deps { 156 for dep_node in node.deps {
160 let dep = PackageDependency { 157 let dep =
161 name: dep_node.name.into(), 158 PackageDependency { name: dep_node.name.into(), pkg: pkg_by_id[&dep_node.pkg] };
162 pkg: pkg_by_id[&dep_node.pkg],
163 };
164 packages[source].dependencies.push(dep); 159 packages[source].dependencies.push(dep);
165 } 160 }
166 } 161 }
@@ -171,8 +166,6 @@ impl CargoWorkspace {
171 self.packages.iter().map(|(id, _pkg)| id) 166 self.packages.iter().map(|(id, _pkg)| id)
172 } 167 }
173 pub fn target_by_root(&self, root: &Path) -> Option<Target> { 168 pub fn target_by_root(&self, root: &Path) -> Option<Target> {
174 self.packages() 169 self.packages().filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)).next()
175 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root))
176 .next()
177 } 170 }
178} 171}
diff --git a/crates/ra_lsp_server/src/project_model/sysroot.rs b/crates/ra_lsp_server/src/project_model/sysroot.rs
index fb4685671..49210ac7a 100644
--- a/crates/ra_lsp_server/src/project_model/sysroot.rs
+++ b/crates/ra_lsp_server/src/project_model/sysroot.rs
@@ -53,9 +53,7 @@ impl Sysroot {
53 ); 53 );
54 } 54 }
55 55
56 let mut sysroot = Sysroot { 56 let mut sysroot = Sysroot { crates: Arena::default() };
57 crates: Arena::default(),
58 };
59 for name in SYSROOT_CRATES.trim().lines() { 57 for name in SYSROOT_CRATES.trim().lines() {
60 let root = src.join(format!("lib{}", name)).join("lib.rs"); 58 let root = src.join(format!("lib{}", name)).join("lib.rs");
61 if root.exists() { 59 if root.exists() {
@@ -77,10 +75,7 @@ impl Sysroot {
77 } 75 }
78 76
79 fn by_name(&self, name: &str) -> Option<SysrootCrate> { 77 fn by_name(&self, name: &str) -> Option<SysrootCrate> {
80 self.crates 78 self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id)
81 .iter()
82 .find(|(_id, data)| data.name == name)
83 .map(|(id, _data)| id)
84 } 79 }
85} 80}
86 81
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index c2167c5d8..02f2a37a8 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -80,10 +80,7 @@ impl ServerWorldState {
80 } 80 }
81 } 81 }
82 82
83 let libstd = ws 83 let libstd = ws.sysroot.std().and_then(|it| sysroot_crates.get(&it).map(|&it| it));
84 .sysroot
85 .std()
86 .and_then(|it| sysroot_crates.get(&it).map(|&it| it));
87 84
88 let mut pkg_to_lib_crate = FxHashMap::default(); 85 let mut pkg_to_lib_crate = FxHashMap::default();
89 let mut pkg_crates = FxHashMap::default(); 86 let mut pkg_crates = FxHashMap::default();
@@ -99,10 +96,7 @@ impl ServerWorldState {
99 lib_tgt = Some(crate_id); 96 lib_tgt = Some(crate_id);
100 pkg_to_lib_crate.insert(pkg, crate_id); 97 pkg_to_lib_crate.insert(pkg, crate_id);
101 } 98 }
102 pkg_crates 99 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
103 .entry(pkg)
104 .or_insert_with(Vec::new)
105 .push(crate_id);
106 } 100 }
107 } 101 }
108 102
@@ -192,18 +186,8 @@ impl ServerWorldState {
192 libs.push((SourceRootId(root.0.into()), files)); 186 libs.push((SourceRootId(root.0.into()), files));
193 } 187 }
194 } 188 }
195 VfsChange::AddFile { 189 VfsChange::AddFile { root, file, path, text } => {
196 root, 190 change.add_file(SourceRootId(root.0.into()), FileId(file.0.into()), path, text);
197 file,
198 path,
199 text,
200 } => {
201 change.add_file(
202 SourceRootId(root.0.into()),
203 FileId(file.0.into()),
204 path,
205 text,
206 );
207 } 191 }
208 VfsChange::RemoveFile { root, file, path } => { 192 VfsChange::RemoveFile { root, file, path } => {
209 change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path) 193 change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path)
@@ -247,9 +231,7 @@ impl ServerWorld {
247 } 231 }
248 232
249 pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> { 233 pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> {
250 let path = uri 234 let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
251 .to_file_path()
252 .map_err(|()| format_err!("invalid uri: {}", uri))?;
253 let file = self 235 let file = self
254 .vfs 236 .vfs
255 .read() 237 .read()
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs
index bfb0645a8..e49c87169 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/main.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs
@@ -55,10 +55,7 @@ fn foo() {
55 ); 55 );
56 server.wait_for_feedback("workspace loaded"); 56 server.wait_for_feedback("workspace loaded");
57 server.request::<Runnables>( 57 server.request::<Runnables>(
58 RunnablesParams { 58 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None },
59 text_document: server.doc_id("lib.rs"),
60 position: None,
61 },
62 json!([ 59 json!([
63 { 60 {
64 "args": [ "test", "--", "foo", "--nocapture" ], 61 "args": [ "test", "--", "foo", "--nocapture" ],
@@ -220,10 +217,7 @@ fn main() {}
220"#, 217"#,
221 ); 218 );
222 server.wait_for_feedback("workspace loaded"); 219 server.wait_for_feedback("workspace loaded");
223 let empty_context = || CodeActionContext { 220 let empty_context = || CodeActionContext { diagnostics: Vec::new(), only: None };
224 diagnostics: Vec::new(),
225 only: None,
226 };
227 server.request::<CodeActionRequest>( 221 server.request::<CodeActionRequest>(
228 CodeActionParams { 222 CodeActionParams {
229 text_document: server.doc_id("src/lib.rs"), 223 text_document: server.doc_id("src/lib.rs"),
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs
index 57a8b4f4d..eee85f8c8 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/support.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs
@@ -83,9 +83,7 @@ impl Server {
83 83
84 pub fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier { 84 pub fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier {
85 let path = self.dir.path().join(rel_path); 85 let path = self.dir.path().join(rel_path);
86 TextDocumentIdentifier { 86 TextDocumentIdentifier { uri: Url::from_file_path(path).unwrap() }
87 uri: Url::from_file_path(path).unwrap(),
88 }
89 } 87 }
90 88
91 pub fn request<R>(&self, params: R::Params, expected_resp: Value) 89 pub fn request<R>(&self, params: R::Params, expected_resp: Value)
@@ -119,11 +117,7 @@ impl Server {
119 } 117 }
120 fn send_request_(&self, r: RawRequest) -> Value { 118 fn send_request_(&self, r: RawRequest) -> Value {
121 let id = r.id; 119 let id = r.id;
122 self.worker 120 self.worker.as_ref().unwrap().send(RawMessage::Request(r)).unwrap();
123 .as_ref()
124 .unwrap()
125 .send(RawMessage::Request(r))
126 .unwrap();
127 while let Some(msg) = self.recv() { 121 while let Some(msg) = self.recv() {
128 match msg { 122 match msg {
129 RawMessage::Request(req) => panic!("unexpected request: {:?}", req), 123 RawMessage::Request(req) => panic!("unexpected request: {:?}", req),
@@ -169,11 +163,7 @@ impl Server {
169 }) 163 })
170 } 164 }
171 fn send_notification(&self, not: RawNotification) { 165 fn send_notification(&self, not: RawNotification) {
172 self.worker 166 self.worker.as_ref().unwrap().send(RawMessage::Notification(not)).unwrap();
173 .as_ref()
174 .unwrap()
175 .send(RawMessage::Notification(not))
176 .unwrap();
177 } 167 }
178} 168}
179 169
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index 2c8ad4429..b09837831 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -137,18 +137,12 @@ impl_froms!(TokenTree: Leaf, Subtree);
137"#; 137"#;
138 138
139 let source_file = ast::SourceFile::parse(macro_definition); 139 let source_file = ast::SourceFile::parse(macro_definition);
140 let macro_definition = source_file 140 let macro_definition =
141 .syntax() 141 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
142 .descendants()
143 .find_map(ast::MacroCall::cast)
144 .unwrap();
145 142
146 let source_file = ast::SourceFile::parse(macro_invocation); 143 let source_file = ast::SourceFile::parse(macro_invocation);
147 let macro_invocation = source_file 144 let macro_invocation =
148 .syntax() 145 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
149 .descendants()
150 .find_map(ast::MacroCall::cast)
151 .unwrap();
152 146
153 let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); 147 let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
154 let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap(); 148 let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
@@ -163,11 +157,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
163 157
164 fn create_rules(macro_definition: &str) -> MacroRules { 158 fn create_rules(macro_definition: &str) -> MacroRules {
165 let source_file = ast::SourceFile::parse(macro_definition); 159 let source_file = ast::SourceFile::parse(macro_definition);
166 let macro_definition = source_file 160 let macro_definition =
167 .syntax() 161 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
168 .descendants()
169 .find_map(ast::MacroCall::cast)
170 .unwrap();
171 162
172 let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); 163 let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
173 crate::MacroRules::parse(&definition_tt).unwrap() 164 crate::MacroRules::parse(&definition_tt).unwrap()
@@ -175,11 +166,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
175 166
176 fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { 167 fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) {
177 let source_file = ast::SourceFile::parse(invocation); 168 let source_file = ast::SourceFile::parse(invocation);
178 let macro_invocation = source_file 169 let macro_invocation =
179 .syntax() 170 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
180 .descendants()
181 .find_map(ast::MacroCall::cast)
182 .unwrap();
183 171
184 let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap(); 172 let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
185 173
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index fb1066eec..31531f4c9 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -133,11 +133,7 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Option<Bindings>
133 } 133 }
134 _ => return None, 134 _ => return None,
135 }, 135 },
136 crate::TokenTree::Repeat(crate::Repeat { 136 crate::TokenTree::Repeat(crate::Repeat { subtree, kind: _, separator }) => {
137 subtree,
138 kind: _,
139 separator,
140 }) => {
141 while let Some(nested) = match_lhs(subtree, input) { 137 while let Some(nested) = match_lhs(subtree, input) {
142 res.push_nested(nested)?; 138 res.push_nested(nested)?;
143 if let Some(separator) = *separator { 139 if let Some(separator) = *separator {
@@ -166,10 +162,7 @@ fn expand_subtree(
166 .map(|it| expand_tt(it, bindings, nesting)) 162 .map(|it| expand_tt(it, bindings, nesting))
167 .collect::<Option<Vec<_>>>()?; 163 .collect::<Option<Vec<_>>>()?;
168 164
169 Some(tt::Subtree { 165 Some(tt::Subtree { token_trees, delimiter: template.delimiter })
170 token_trees,
171 delimiter: template.delimiter,
172 })
173} 166}
174 167
175fn expand_tt( 168fn expand_tt(
@@ -188,23 +181,15 @@ fn expand_tt(
188 token_trees.push(t.into()) 181 token_trees.push(t.into())
189 } 182 }
190 nesting.pop().unwrap(); 183 nesting.pop().unwrap();
191 tt::Subtree { 184 tt::Subtree { token_trees, delimiter: tt::Delimiter::None }.into()
192 token_trees,
193 delimiter: tt::Delimiter::None,
194 }
195 .into()
196 } 185 }
197 crate::TokenTree::Leaf(leaf) => match leaf { 186 crate::TokenTree::Leaf(leaf) => match leaf {
198 crate::Leaf::Ident(ident) => tt::Leaf::from(tt::Ident { 187 crate::Leaf::Ident(ident) => {
199 text: ident.text.clone(), 188 tt::Leaf::from(tt::Ident { text: ident.text.clone() }).into()
200 }) 189 }
201 .into(),
202 crate::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(), 190 crate::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(),
203 crate::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(), 191 crate::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(),
204 crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { 192 crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(),
205 text: l.text.clone(),
206 })
207 .into(),
208 }, 193 },
209 }; 194 };
210 Some(res) 195 Some(res)
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs
index abad2e8c8..60e566ed2 100644
--- a/crates/ra_mbe/src/mbe_parser.rs
+++ b/crates/ra_mbe/src/mbe_parser.rs
@@ -52,10 +52,7 @@ fn parse_subtree(tt: &tt::Subtree) -> Option<crate::Subtree> {
52 }; 52 };
53 token_trees.push(child); 53 token_trees.push(child);
54 } 54 }
55 Some(crate::Subtree { 55 Some(crate::Subtree { token_trees, delimiter: tt.delimiter })
56 token_trees,
57 delimiter: tt.delimiter,
58 })
59} 56}
60 57
61fn parse_var(p: &mut TtCursor) -> Option<crate::Var> { 58fn parse_var(p: &mut TtCursor) -> Option<crate::Var> {
@@ -92,9 +89,5 @@ fn parse_repeat(p: &mut TtCursor) -> Option<crate::Repeat> {
92 _ => return None, 89 _ => return None,
93 }; 90 };
94 p.bump(); 91 p.bump();
95 Some(crate::Repeat { 92 Some(crate::Repeat { subtree, kind, separator })
96 subtree,
97 kind,
98 separator,
99 })
100} 93}
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 2dc04d4e7..9a2eceaba 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -23,23 +23,14 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
23 for char in child.leaf_text().unwrap().chars() { 23 for char in child.leaf_text().unwrap().chars() {
24 if let Some(char) = prev { 24 if let Some(char) = prev {
25 token_trees.push( 25 token_trees.push(
26 tt::Leaf::from(tt::Punct { 26 tt::Leaf::from(tt::Punct { char, spacing: tt::Spacing::Joint }).into(),
27 char,
28 spacing: tt::Spacing::Joint,
29 })
30 .into(),
31 ); 27 );
32 } 28 }
33 prev = Some(char) 29 prev = Some(char)
34 } 30 }
35 if let Some(char) = prev { 31 if let Some(char) = prev {
36 token_trees.push( 32 token_trees
37 tt::Leaf::from(tt::Punct { 33 .push(tt::Leaf::from(tt::Punct { char, spacing: tt::Spacing::Alone }).into());
38 char,
39 spacing: tt::Spacing::Alone,
40 })
41 .into(),
42 );
43 } 34 }
44 } else { 35 } else {
45 let child: tt::TokenTree = if child.kind() == TOKEN_TREE { 36 let child: tt::TokenTree = if child.kind() == TOKEN_TREE {
@@ -48,10 +39,7 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
48 let text = child.leaf_text().unwrap().clone(); 39 let text = child.leaf_text().unwrap().clone();
49 tt::Leaf::from(tt::Ident { text }).into() 40 tt::Leaf::from(tt::Ident { text }).into()
50 } else if child.kind().is_literal() { 41 } else if child.kind().is_literal() {
51 tt::Leaf::from(tt::Literal { 42 tt::Leaf::from(tt::Literal { text: child.leaf_text().unwrap().clone() }).into()
52 text: child.leaf_text().unwrap().clone(),
53 })
54 .into()
55 } else { 43 } else {
56 return None; 44 return None;
57 }; 45 };
@@ -59,9 +47,6 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
59 } 47 }
60 } 48 }
61 49
62 let res = tt::Subtree { 50 let res = tt::Subtree { delimiter, token_trees };
63 delimiter,
64 token_trees,
65 };
66 Some(res) 51 Some(res)
67} 52}
diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs
index 38f21594c..81a99228f 100644
--- a/crates/ra_syntax/src/algo/visit.rs
+++ b/crates/ra_syntax/src/algo/visit.rs
@@ -7,10 +7,7 @@ pub fn visitor<'a, T>() -> impl Visitor<'a, Output = T> {
7} 7}
8 8
9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output = T, Ctx = C> { 9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output = T, Ctx = C> {
10 EmptyVisitorCtx { 10 EmptyVisitorCtx { ph: PhantomData, ctx }
11 ph: PhantomData,
12 ctx,
13 }
14} 11}
15 12
16pub trait Visitor<'a>: Sized { 13pub trait Visitor<'a>: Sized {
@@ -21,11 +18,7 @@ pub trait Visitor<'a>: Sized {
21 N: AstNode + 'a, 18 N: AstNode + 'a,
22 F: FnOnce(&'a N) -> Self::Output, 19 F: FnOnce(&'a N) -> Self::Output,
23 { 20 {
24 Vis { 21 Vis { inner: self, f, ph: PhantomData }
25 inner: self,
26 f,
27 ph: PhantomData,
28 }
29 } 22 }
30} 23}
31 24
@@ -38,11 +31,7 @@ pub trait VisitorCtx<'a>: Sized {
38 N: AstNode + 'a, 31 N: AstNode + 'a,
39 F: FnOnce(&'a N, Self::Ctx) -> Self::Output, 32 F: FnOnce(&'a N, Self::Ctx) -> Self::Output,
40 { 33 {
41 VisCtx { 34 VisCtx { inner: self, f, ph: PhantomData }
42 inner: self,
43 f,
44 ph: PhantomData,
45 }
46 } 35 }
47} 36}
48 37
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index d6237532b..cf5cfecc2 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -127,16 +127,12 @@ pub trait DocCommentsOwner: AstNode {
127 let line = comment.text().as_str(); 127 let line = comment.text().as_str();
128 128
129 // Determine if the prefix or prefix + 1 char is stripped 129 // Determine if the prefix or prefix + 1 char is stripped
130 let pos = if line 130 let pos =
131 .chars() 131 if line.chars().nth(prefix_len).map(|c| c.is_whitespace()).unwrap_or(false) {
132 .nth(prefix_len) 132 prefix_len + 1
133 .map(|c| c.is_whitespace()) 133 } else {
134 .unwrap_or(false) 134 prefix_len
135 { 135 };
136 prefix_len + 1
137 } else {
138 prefix_len
139 };
140 136
141 line[pos..].to_owned() 137 line[pos..].to_owned()
142 }) 138 })
@@ -357,10 +353,7 @@ pub enum PathSegmentKind<'a> {
357 353
358impl PathSegment { 354impl PathSegment {
359 pub fn parent_path(&self) -> &Path { 355 pub fn parent_path(&self) -> &Path {
360 self.syntax() 356 self.syntax().parent().and_then(Path::cast).expect("segments are always nested in paths")
361 .parent()
362 .and_then(Path::cast)
363 .expect("segments are always nested in paths")
364 } 357 }
365 358
366 pub fn kind(&self) -> Option<PathSegmentKind> { 359 pub fn kind(&self) -> Option<PathSegmentKind> {
@@ -428,10 +421,7 @@ pub struct AstChildren<'a, N> {
428 421
429impl<'a, N> AstChildren<'a, N> { 422impl<'a, N> AstChildren<'a, N> {
430 fn new(parent: &'a SyntaxNode) -> Self { 423 fn new(parent: &'a SyntaxNode) -> Self {
431 AstChildren { 424 AstChildren { inner: parent.children(), ph: PhantomData }
432 inner: parent.children(),
433 ph: PhantomData,
434 }
435 } 425 }
436} 426}
437 427
@@ -658,11 +648,7 @@ impl SelfParam {
658 let borrowed = self.syntax().children().any(|n| n.kind() == AMP); 648 let borrowed = self.syntax().children().any(|n| n.kind() == AMP);
659 if borrowed { 649 if borrowed {
660 // check for a `mut` coming after the & -- `mut &self` != `&mut self` 650 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
661 if self 651 if self.syntax().children().skip_while(|n| n.kind() != AMP).any(|n| n.kind() == MUT_KW)
662 .syntax()
663 .children()
664 .skip_while(|n| n.kind() != AMP)
665 .any(|n| n.kind() == MUT_KW)
666 { 652 {
667 SelfParamFlavor::MutRef 653 SelfParamFlavor::MutRef
668 } else { 654 } else {
@@ -769,8 +755,5 @@ fn test_doc_comment_preserves_indents() {
769 "#, 755 "#,
770 ); 756 );
771 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 757 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
772 assert_eq!( 758 assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap());
773 "doc1\n```\nfn foo() {\n // ...\n}\n```",
774 module.doc_comment_text().unwrap()
775 );
776} 759}
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 6b88c5685..28fcb1f7d 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -7,26 +7,17 @@ use super::*;
7const EXPR_FIRST: TokenSet = LHS_FIRST; 7const EXPR_FIRST: TokenSet = LHS_FIRST;
8 8
9pub(super) fn expr(p: &mut Parser) -> BlockLike { 9pub(super) fn expr(p: &mut Parser) -> BlockLike {
10 let r = Restrictions { 10 let r = Restrictions { forbid_structs: false, prefer_stmt: false };
11 forbid_structs: false,
12 prefer_stmt: false,
13 };
14 expr_bp(p, r, 1) 11 expr_bp(p, r, 1)
15} 12}
16 13
17pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike { 14pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike {
18 let r = Restrictions { 15 let r = Restrictions { forbid_structs: false, prefer_stmt: true };
19 forbid_structs: false,
20 prefer_stmt: true,
21 };
22 expr_bp(p, r, 1) 16 expr_bp(p, r, 1)
23} 17}
24 18
25fn expr_no_struct(p: &mut Parser) { 19fn expr_no_struct(p: &mut Parser) {
26 let r = Restrictions { 20 let r = Restrictions { forbid_structs: true, prefer_stmt: false };
27 forbid_structs: true,
28 prefer_stmt: false,
29 };
30 expr_bp(p, r, 1); 21 expr_bp(p, r, 1);
31} 22}
32 23
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 600774afd..27ba87657 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -141,14 +141,7 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
141 } 141 }
142 } 142 }
143 p.expect(R_PAREN); 143 p.expect(R_PAREN);
144 m.complete( 144 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
145 p,
146 if saw_expr && !saw_comma {
147 PAREN_EXPR
148 } else {
149 TUPLE_EXPR
150 },
151 )
152} 145}
153 146
154// test array_expr 147// test array_expr
diff --git a/crates/ra_syntax/src/grammar/items.rs b/crates/ra_syntax/src/grammar/items.rs
index 84c18a293..a61f260cf 100644
--- a/crates/ra_syntax/src/grammar/items.rs
+++ b/crates/ra_syntax/src/grammar/items.rs
@@ -155,11 +155,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
155 IMPL_BLOCK 155 IMPL_BLOCK
156 } 156 }
157 _ => { 157 _ => {
158 return if has_mods { 158 return if has_mods { MaybeItem::Modifiers } else { MaybeItem::None };
159 MaybeItem::Modifiers
160 } else {
161 MaybeItem::None
162 };
163 } 159 }
164 }; 160 };
165 161
diff --git a/crates/ra_syntax/src/grammar/params.rs b/crates/ra_syntax/src/grammar/params.rs
index 13158429a..185386569 100644
--- a/crates/ra_syntax/src/grammar/params.rs
+++ b/crates/ra_syntax/src/grammar/params.rs
@@ -36,11 +36,7 @@ impl Flavor {
36} 36}
37 37
38fn list_(p: &mut Parser, flavor: Flavor) { 38fn list_(p: &mut Parser, flavor: Flavor) {
39 let (bra, ket) = if flavor.type_required() { 39 let (bra, ket) = if flavor.type_required() { (L_PAREN, R_PAREN) } else { (PIPE, PIPE) };
40 (L_PAREN, R_PAREN)
41 } else {
42 (PIPE, PIPE)
43 };
44 assert!(p.at(bra)); 40 assert!(p.at(bra));
45 let m = p.start(); 41 let m = p.start();
46 p.bump(); 42 p.bump();
diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs
index 1ac5efdf6..f3f400ae0 100644
--- a/crates/ra_syntax/src/grammar/patterns.rs
+++ b/crates/ra_syntax/src/grammar/patterns.rs
@@ -2,9 +2,7 @@ use super::*;
2 2
3pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST 3pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
4 .union(paths::PATH_FIRST) 4 .union(paths::PATH_FIRST)
5 .union(token_set![ 5 .union(token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE]);
6 REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE
7 ]);
8 6
9pub(super) fn pattern(p: &mut Parser) { 7pub(super) fn pattern(p: &mut Parser) {
10 pattern_r(p, PAT_RECOVERY_SET) 8 pattern_r(p, PAT_RECOVERY_SET)
diff --git a/crates/ra_syntax/src/lexer/ptr.rs b/crates/ra_syntax/src/lexer/ptr.rs
index 0a473c991..c341c4176 100644
--- a/crates/ra_syntax/src/lexer/ptr.rs
+++ b/crates/ra_syntax/src/lexer/ptr.rs
@@ -11,10 +11,7 @@ pub(crate) struct Ptr<'s> {
11impl<'s> Ptr<'s> { 11impl<'s> Ptr<'s> {
12 /// Creates a new `Ptr` from a string. 12 /// Creates a new `Ptr` from a string.
13 pub fn new(text: &'s str) -> Ptr<'s> { 13 pub fn new(text: &'s str) -> Ptr<'s> {
14 Ptr { 14 Ptr { text, len: 0.into() }
15 text,
16 len: 0.into(),
17 }
18 } 15 }
19 16
20 /// Gets the length of the remaining string. 17 /// Gets the length of the remaining string.
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 104f32851..088b2f5d7 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -11,11 +11,7 @@
11//! [rfc#2256]: <https://github.com/rust-lang/rfcs/pull/2256> 11//! [rfc#2256]: <https://github.com/rust-lang/rfcs/pull/2256>
12//! [RFC.md]: <https://github.com/matklad/libsyntax2/blob/master/docs/RFC.md> 12//! [RFC.md]: <https://github.com/matklad/libsyntax2/blob/master/docs/RFC.md>
13 13
14#![forbid( 14#![forbid(missing_debug_implementations, unconditional_recursion, future_incompatible)]
15 missing_debug_implementations,
16 unconditional_recursion,
17 future_incompatible
18)]
19#![deny(bad_style, missing_docs)] 15#![deny(bad_style, missing_docs)]
20#![allow(missing_docs)] 16#![allow(missing_docs)]
21//#![warn(unreachable_pub)] // rust-lang/rust#47816 17//#![warn(unreachable_pub)] // rust-lang/rust#47816
@@ -70,8 +66,7 @@ impl SourceFile {
70 } 66 }
71 67
72 pub fn reparse(&self, edit: &AtomTextEdit) -> TreeArc<SourceFile> { 68 pub fn reparse(&self, edit: &AtomTextEdit) -> TreeArc<SourceFile> {
73 self.incremental_reparse(edit) 69 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
74 .unwrap_or_else(|| self.full_reparse(edit))
75 } 70 }
76 71
77 pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<TreeArc<SourceFile>> { 72 pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<TreeArc<SourceFile>> {
diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs
index 3148371c5..504df753e 100644
--- a/crates/ra_syntax/src/parser_api.rs
+++ b/crates/ra_syntax/src/parser_api.rs
@@ -136,10 +136,7 @@ pub(crate) struct Marker {
136 136
137impl Marker { 137impl Marker {
138 fn new(pos: u32) -> Marker { 138 fn new(pos: u32) -> Marker {
139 Marker { 139 Marker { pos, bomb: DropBomb::new("Marker must be either completed or abandoned") }
140 pos,
141 bomb: DropBomb::new("Marker must be either completed or abandoned"),
142 }
143 } 140 }
144 141
145 /// Finishes the syntax tree node and assigns `kind` to it, 142 /// Finishes the syntax tree node and assigns `kind` to it,
diff --git a/crates/ra_syntax/src/parser_impl.rs b/crates/ra_syntax/src/parser_impl.rs
index 01a51cd8d..f255dc23b 100644
--- a/crates/ra_syntax/src/parser_impl.rs
+++ b/crates/ra_syntax/src/parser_impl.rs
@@ -54,9 +54,7 @@ pub(crate) fn parse_with<S: Sink>(
54 parser(&mut parser_api); 54 parser(&mut parser_api);
55 parser_api.0.into_events() 55 parser_api.0.into_events()
56 }; 56 };
57 EventProcessor::new(sink, text, tokens, &mut events) 57 EventProcessor::new(sink, text, tokens, &mut events).process().finish()
58 .process()
59 .finish()
60} 58}
61 59
62/// Implementation details of `Parser`, extracted 60/// Implementation details of `Parser`, extracted
@@ -160,17 +158,13 @@ impl<'t> ParserImpl<'t> {
160 158
161 /// Append one Error event to the back of events. 159 /// Append one Error event to the back of events.
162 pub(super) fn error(&mut self, msg: String) { 160 pub(super) fn error(&mut self, msg: String) {
163 self.push_event(Event::Error { 161 self.push_event(Event::Error { msg: ParseError(msg) })
164 msg: ParseError(msg),
165 })
166 } 162 }
167 163
168 /// Complete an event with appending a `Finish` event. 164 /// Complete an event with appending a `Finish` event.
169 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) { 165 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) {
170 match self.events[pos as usize] { 166 match self.events[pos as usize] {
171 Event::Start { 167 Event::Start { kind: ref mut slot, .. } => {
172 kind: ref mut slot, ..
173 } => {
174 *slot = kind; 168 *slot = kind;
175 } 169 }
176 _ => unreachable!(), 170 _ => unreachable!(),
@@ -183,10 +177,7 @@ impl<'t> ParserImpl<'t> {
183 let idx = pos as usize; 177 let idx = pos as usize;
184 if idx == self.events.len() - 1 { 178 if idx == self.events.len() - 1 {
185 match self.events.pop() { 179 match self.events.pop() {
186 Some(Event::Start { 180 Some(Event::Start { kind: TOMBSTONE, forward_parent: None }) => (),
187 kind: TOMBSTONE,
188 forward_parent: None,
189 }) => (),
190 _ => unreachable!(), 181 _ => unreachable!(),
191 } 182 }
192 } 183 }
@@ -196,10 +187,7 @@ impl<'t> ParserImpl<'t> {
196 pub(super) fn precede(&mut self, pos: u32) -> u32 { 187 pub(super) fn precede(&mut self, pos: u32) -> u32 {
197 let new_pos = self.start(); 188 let new_pos = self.start();
198 match self.events[pos as usize] { 189 match self.events[pos as usize] {
199 Event::Start { 190 Event::Start { ref mut forward_parent, .. } => {
200 ref mut forward_parent,
201 ..
202 } => {
203 *forward_parent = Some(new_pos - pos); 191 *forward_parent = Some(new_pos - pos);
204 } 192 }
205 _ => unreachable!(), 193 _ => unreachable!(),
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs
index 33e10ef85..677876ab5 100644
--- a/crates/ra_syntax/src/parser_impl/event.rs
+++ b/crates/ra_syntax/src/parser_impl/event.rs
@@ -86,10 +86,7 @@ pub(crate) enum Event {
86 86
87impl Event { 87impl Event {
88 pub(crate) fn tombstone() -> Self { 88 pub(crate) fn tombstone() -> Self {
89 Event::Start { 89 Event::Start { kind: TOMBSTONE, forward_parent: None }
90 kind: TOMBSTONE,
91 forward_parent: None,
92 }
93 } 90 }
94} 91}
95 92
@@ -109,14 +106,7 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
109 tokens: &'a [Token], 106 tokens: &'a [Token],
110 events: &'a mut [Event], 107 events: &'a mut [Event],
111 ) -> EventProcessor<'a, S> { 108 ) -> EventProcessor<'a, S> {
112 EventProcessor { 109 EventProcessor { sink, text_pos: 0.into(), text, token_pos: 0, tokens, events }
113 sink,
114 text_pos: 0.into(),
115 text,
116 token_pos: 0,
117 tokens,
118 events,
119 }
120 } 110 }
121 111
122 /// Generate the syntax tree with the control of events. 112 /// Generate the syntax tree with the control of events.
@@ -125,14 +115,9 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
125 115
126 for i in 0..self.events.len() { 116 for i in 0..self.events.len() {
127 match mem::replace(&mut self.events[i], Event::tombstone()) { 117 match mem::replace(&mut self.events[i], Event::tombstone()) {
128 Event::Start { 118 Event::Start { kind: TOMBSTONE, .. } => (),
129 kind: TOMBSTONE, ..
130 } => (),
131 119
132 Event::Start { 120 Event::Start { kind, forward_parent } => {
133 kind,
134 forward_parent,
135 } => {
136 // For events[A, B, C], B is A's forward_parent, C is B's forward_parent, 121 // For events[A, B, C], B is A's forward_parent, C is B's forward_parent,
137 // in the normal control flow, the parent-child relation: `A -> B -> C`, 122 // in the normal control flow, the parent-child relation: `A -> B -> C`,
138 // while with the magic forward_parent, it writes: `C <- B <- A`. 123 // while with the magic forward_parent, it writes: `C <- B <- A`.
@@ -145,10 +130,7 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
145 idx += fwd as usize; 130 idx += fwd as usize;
146 // append `A`'s forward_parent `B` 131 // append `A`'s forward_parent `B`
147 fp = match mem::replace(&mut self.events[idx], Event::tombstone()) { 132 fp = match mem::replace(&mut self.events[idx], Event::tombstone()) {
148 Event::Start { 133 Event::Start { kind, forward_parent } => {
149 kind,
150 forward_parent,
151 } => {
152 forward_parents.push(kind); 134 forward_parents.push(kind);
153 forward_parent 135 forward_parent
154 } 136 }
@@ -174,10 +156,9 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
174 .sum::<TextUnit>(); 156 .sum::<TextUnit>();
175 self.leaf(kind, len, n_raw_tokens); 157 self.leaf(kind, len, n_raw_tokens);
176 } 158 }
177 Event::Error { msg } => self.sink.error(SyntaxError::new( 159 Event::Error { msg } => self
178 SyntaxErrorKind::ParseError(msg), 160 .sink
179 self.text_pos, 161 .error(SyntaxError::new(SyntaxErrorKind::ParseError(msg), self.text_pos)),
180 )),
181 } 162 }
182 } 163 }
183 self.sink 164 self.sink
@@ -189,10 +170,8 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
189 self.sink.start_branch(kind); 170 self.sink.start_branch(kind);
190 return; 171 return;
191 } 172 }
192 let n_trivias = self.tokens[self.token_pos..] 173 let n_trivias =
193 .iter() 174 self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count();
194 .take_while(|it| it.kind.is_trivia())
195 .count();
196 let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias]; 175 let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
197 let mut trivia_end = 176 let mut trivia_end =
198 self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextUnit>(); 177 self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextUnit>();
diff --git a/crates/ra_syntax/src/parser_impl/input.rs b/crates/ra_syntax/src/parser_impl/input.rs
index 7fde5b3ab..616a26fdc 100644
--- a/crates/ra_syntax/src/parser_impl/input.rs
+++ b/crates/ra_syntax/src/parser_impl/input.rs
@@ -36,11 +36,7 @@ impl<'t> ParserInput<'t> {
36 len += token.len; 36 len += token.len;
37 } 37 }
38 38
39 ParserInput { 39 ParserInput { text, start_offsets, tokens }
40 text,
41 start_offsets,
42 tokens,
43 }
44 } 40 }
45 41
46 /// Get the syntax kind of token at given input position. 42 /// Get the syntax kind of token at given input position.
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 13ee1305f..aae590cb6 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -15,16 +15,12 @@ pub struct SyntaxNodePtr {
15 15
16impl SyntaxNodePtr { 16impl SyntaxNodePtr {
17 pub fn new(node: &SyntaxNode) -> SyntaxNodePtr { 17 pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
18 SyntaxNodePtr { 18 SyntaxNodePtr { range: node.range(), kind: node.kind() }
19 range: node.range(),
20 kind: node.kind(),
21 }
22 } 19 }
23 20
24 pub fn to_node(self, source_file: &SourceFile) -> &SyntaxNode { 21 pub fn to_node(self, source_file: &SourceFile) -> &SyntaxNode {
25 generate(Some(source_file.syntax()), |&node| { 22 generate(Some(source_file.syntax()), |&node| {
26 node.children() 23 node.children().find(|it| self.range.is_subrange(&it.range()))
27 .find(|it| self.range.is_subrange(&it.range()))
28 }) 24 })
29 .find(|it| it.range() == self.range && it.kind() == self.kind) 25 .find(|it| it.range() == self.range && it.kind() == self.kind)
30 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) 26 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
@@ -55,10 +51,7 @@ impl<N: AstNode> Clone for AstPtr<N> {
55 51
56impl<N: AstNode> AstPtr<N> { 52impl<N: AstNode> AstPtr<N> {
57 pub fn new(node: &N) -> AstPtr<N> { 53 pub fn new(node: &N) -> AstPtr<N> {
58 AstPtr { 54 AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }
59 raw: SyntaxNodePtr::new(node.syntax()),
60 _ty: PhantomData,
61 }
62 } 55 }
63 56
64 pub fn to_node(self, source_file: &SourceFile) -> &N { 57 pub fn to_node(self, source_file: &SourceFile) -> &N {
@@ -76,11 +69,7 @@ fn test_local_syntax_ptr() {
76 use crate::{ast, AstNode}; 69 use crate::{ast, AstNode};
77 70
78 let file = SourceFile::parse("struct Foo { f: u32, }"); 71 let file = SourceFile::parse("struct Foo { f: u32, }");
79 let field = file 72 let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap();
80 .syntax()
81 .descendants()
82 .find_map(ast::NamedFieldDef::cast)
83 .unwrap();
84 let ptr = SyntaxNodePtr::new(field.syntax()); 73 let ptr = SyntaxNodePtr::new(field.syntax());
85 let field_syntax = ptr.to_node(&file); 74 let field_syntax = ptr.to_node(&file);
86 assert_eq!(field.syntax(), &*field_syntax); 75 assert_eq!(field.syntax(), &*field_syntax);
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs
index 2f1de6b02..c5c609ad5 100644
--- a/crates/ra_syntax/src/reparsing.rs
+++ b/crates/ra_syntax/src/reparsing.rs
@@ -75,10 +75,7 @@ fn is_contextual_kw(text: &str) -> bool {
75type ParseFn = fn(&mut Parser); 75type ParseFn = fn(&mut Parser);
76fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(&SyntaxNode, ParseFn)> { 76fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(&SyntaxNode, ParseFn)> {
77 let node = algo::find_covering_node(node, range); 77 let node = algo::find_covering_node(node, range);
78 return node 78 return node.ancestors().filter_map(|node| reparser(node).map(|r| (node, r))).next();
79 .ancestors()
80 .filter_map(|node| reparser(node).map(|r| (node, r)))
81 .next();
82 79
83 fn reparser(node: &SyntaxNode) -> Option<ParseFn> { 80 fn reparser(node: &SyntaxNode) -> Option<ParseFn> {
84 let res = match node.kind() { 81 let res = match node.kind() {
@@ -169,10 +166,7 @@ mod tests {
169 let fully_reparsed = SourceFile::parse(&after); 166 let fully_reparsed = SourceFile::parse(&after);
170 let incrementally_reparsed = { 167 let incrementally_reparsed = {
171 let f = SourceFile::parse(&before); 168 let f = SourceFile::parse(&before);
172 let edit = AtomTextEdit { 169 let edit = AtomTextEdit { delete: range, insert: replace_with.to_string() };
173 delete: range,
174 insert: replace_with.to_string(),
175 };
176 let (node, green, new_errors) = 170 let (node, green, new_errors) =
177 reparser(f.syntax(), &edit).expect("cannot incrementally reparse"); 171 reparser(f.syntax(), &edit).expect("cannot incrementally reparse");
178 let green_root = node.replace_with(green); 172 let green_root = node.replace_with(green);
diff --git a/crates/ra_syntax/src/string_lexing/parser.rs b/crates/ra_syntax/src/string_lexing/parser.rs
index e835382fc..7469eb903 100644
--- a/crates/ra_syntax/src/string_lexing/parser.rs
+++ b/crates/ra_syntax/src/string_lexing/parser.rs
@@ -24,9 +24,7 @@ impl<'a> Parser<'a> {
24 } 24 }
25 25
26 pub fn advance(&mut self) -> char { 26 pub fn advance(&mut self) -> char {
27 let next = self 27 let next = self.peek().expect("cannot advance if end of input is reached");
28 .peek()
29 .expect("cannot advance if end of input is reached");
30 self.pos += next.len_utf8(); 28 self.pos += next.len_utf8();
31 next 29 next
32 } 30 }
@@ -133,10 +131,7 @@ impl<'a> Parser<'a> {
133 Some(self.parse_escape(start)) 131 Some(self.parse_escape(start))
134 } else { 132 } else {
135 let end = self.get_pos(); 133 let end = self.get_pos();
136 Some(StringComponent::new( 134 Some(StringComponent::new(TextRange::from_to(start, end), CodePoint))
137 TextRange::from_to(start, end),
138 CodePoint,
139 ))
140 } 135 }
141 } 136 }
142 137
diff --git a/crates/ra_syntax/src/string_lexing/string.rs b/crates/ra_syntax/src/string_lexing/string.rs
index 064f08544..a4742a0d1 100644
--- a/crates/ra_syntax/src/string_lexing/string.rs
+++ b/crates/ra_syntax/src/string_lexing/string.rs
@@ -120,12 +120,7 @@ mod tests {
120 fn closed_char_component(src: &str) -> StringComponent { 120 fn closed_char_component(src: &str) -> StringComponent {
121 let (has_closing_quote, components) = parse(src); 121 let (has_closing_quote, components) = parse(src);
122 assert!(has_closing_quote, "char should have closing quote"); 122 assert!(has_closing_quote, "char should have closing quote");
123 assert!( 123 assert!(components.len() == 1, "Literal: {}\nComponents: {:#?}", src, components);
124 components.len() == 1,
125 "Literal: {}\nComponents: {:#?}",
126 src,
127 components
128 );
129 components[0].clone() 124 components[0].clone()
130 } 125 }
131 126
diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs
index 9e1949124..4e77c15b6 100644
--- a/crates/ra_syntax/src/validation/block.rs
+++ b/crates/ra_syntax/src/validation/block.rs
@@ -17,8 +17,6 @@ pub(crate) fn validate_block_node(node: &ast::Block, errors: &mut Vec<SyntaxErro
17 _ => {} 17 _ => {}
18 } 18 }
19 } 19 }
20 errors.extend( 20 errors
21 node.attrs() 21 .extend(node.attrs().map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().range())))
22 .map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().range())),
23 )
24} 22}
diff --git a/crates/ra_syntax/src/validation/byte.rs b/crates/ra_syntax/src/validation/byte.rs
index 9bddabc80..d51fabcf9 100644
--- a/crates/ra_syntax/src/validation/byte.rs
+++ b/crates/ra_syntax/src/validation/byte.rs
@@ -28,10 +28,7 @@ pub(super) fn validate_byte_node(node: &ast::Byte, errors: &mut Vec<SyntaxError>
28 } 28 }
29 29
30 if let Some(range) = components.suffix { 30 if let Some(range) = components.suffix {
31 errors.push(SyntaxError::new( 31 errors.push(SyntaxError::new(InvalidSuffix, range + literal_range.start()));
32 InvalidSuffix,
33 range + literal_range.start(),
34 ));
35 } 32 }
36 33
37 if len == 0 { 34 if len == 0 {
@@ -55,10 +52,7 @@ pub(super) fn validate_byte_component(
55 AsciiCodeEscape => validate_byte_code_escape(text, range, errors), 52 AsciiCodeEscape => validate_byte_code_escape(text, range, errors),
56 UnicodeEscape => errors.push(SyntaxError::new(UnicodeEscapeForbidden, range)), 53 UnicodeEscape => errors.push(SyntaxError::new(UnicodeEscapeForbidden, range)),
57 CodePoint => { 54 CodePoint => {
58 let c = text 55 let c = text.chars().next().expect("Code points should be one character long");
59 .chars()
60 .next()
61 .expect("Code points should be one character long");
62 56
63 // These bytes must always be escaped 57 // These bytes must always be escaped
64 if c == '\t' || c == '\r' || c == '\n' { 58 if c == '\t' || c == '\r' || c == '\n' {
@@ -93,10 +87,7 @@ fn validate_byte_code_escape(text: &str, range: TextRange, errors: &mut Vec<Synt
93 } else if text.chars().count() < 4 { 87 } else if text.chars().count() < 4 {
94 errors.push(SyntaxError::new(TooShortByteCodeEscape, range)); 88 errors.push(SyntaxError::new(TooShortByteCodeEscape, range));
95 } else { 89 } else {
96 assert!( 90 assert!(text.chars().count() == 4, "ByteCodeEscape cannot be longer than 4 chars");
97 text.chars().count() == 4,
98 "ByteCodeEscape cannot be longer than 4 chars"
99 );
100 91
101 if u8::from_str_radix(&text[2..], 16).is_err() { 92 if u8::from_str_radix(&text[2..], 16).is_err() {
102 errors.push(SyntaxError::new(MalformedByteCodeEscape, range)); 93 errors.push(SyntaxError::new(MalformedByteCodeEscape, range));
@@ -115,12 +106,7 @@ mod test {
115 106
116 fn assert_valid_byte(literal: &str) { 107 fn assert_valid_byte(literal: &str) {
117 let file = build_file(literal); 108 let file = build_file(literal);
118 assert!( 109 assert!(file.errors().len() == 0, "Errors for literal '{}': {:?}", literal, file.errors());
119 file.errors().len() == 0,
120 "Errors for literal '{}': {:?}",
121 literal,
122 file.errors()
123 );
124 } 110 }
125 111
126 fn assert_invalid_byte(literal: &str) { 112 fn assert_invalid_byte(literal: &str) {
@@ -193,13 +179,7 @@ mod test {
193 179
194 #[test] 180 #[test]
195 fn test_invalid_unicode_escape() { 181 fn test_invalid_unicode_escape() {
196 let well_formed = [ 182 let well_formed = [r"\u{FF}", r"\u{0}", r"\u{F}", r"\u{10FFFF}", r"\u{1_0__FF___FF_____}"];
197 r"\u{FF}",
198 r"\u{0}",
199 r"\u{F}",
200 r"\u{10FFFF}",
201 r"\u{1_0__FF___FF_____}",
202 ];
203 for c in &well_formed { 183 for c in &well_formed {
204 assert_invalid_byte(c); 184 assert_invalid_byte(c);
205 } 185 }
diff --git a/crates/ra_syntax/src/validation/byte_string.rs b/crates/ra_syntax/src/validation/byte_string.rs
index bdb147545..7abe8f330 100644
--- a/crates/ra_syntax/src/validation/byte_string.rs
+++ b/crates/ra_syntax/src/validation/byte_string.rs
@@ -34,10 +34,7 @@ pub(crate) fn validate_byte_string_node(node: &ast::ByteString, errors: &mut Vec
34 } 34 }
35 35
36 if let Some(range) = components.suffix { 36 if let Some(range) = components.suffix {
37 errors.push(SyntaxError::new( 37 errors.push(SyntaxError::new(InvalidSuffix, range + literal_range.start()));
38 InvalidSuffix,
39 range + literal_range.start(),
40 ));
41 } 38 }
42} 39}
43 40
@@ -53,12 +50,7 @@ mod test {
53 50
54 fn assert_valid_str(literal: &str) { 51 fn assert_valid_str(literal: &str) {
55 let file = build_file(literal); 52 let file = build_file(literal);
56 assert!( 53 assert!(file.errors().len() == 0, "Errors for literal '{}': {:?}", literal, file.errors());
57 file.errors().len() == 0,
58 "Errors for literal '{}': {:?}",
59 literal,
60 file.errors()
61 );
62 } 54 }
63 55
64 fn assert_invalid_str(literal: &str) { 56 fn assert_invalid_str(literal: &str) {
@@ -130,13 +122,7 @@ mod test {
130 122
131 #[test] 123 #[test]
132 fn test_invalid_unicode_escape() { 124 fn test_invalid_unicode_escape() {
133 let well_formed = [ 125 let well_formed = [r"\u{FF}", r"\u{0}", r"\u{F}", r"\u{10FFFF}", r"\u{1_0__FF___FF_____}"];
134 r"\u{FF}",
135 r"\u{0}",
136 r"\u{F}",
137 r"\u{10FFFF}",
138 r"\u{1_0__FF___FF_____}",
139 ];
140 for c in &well_formed { 126 for c in &well_formed {
141 assert_invalid_str(c); 127 assert_invalid_str(c);
142 } 128 }
diff --git a/crates/ra_syntax/src/validation/char.rs b/crates/ra_syntax/src/validation/char.rs
index e3ac5836b..012594db3 100644
--- a/crates/ra_syntax/src/validation/char.rs
+++ b/crates/ra_syntax/src/validation/char.rs
@@ -31,10 +31,7 @@ pub(super) fn validate_char_node(node: &ast::Char, errors: &mut Vec<SyntaxError>
31 } 31 }
32 32
33 if let Some(range) = components.suffix { 33 if let Some(range) = components.suffix {
34 errors.push(SyntaxError::new( 34 errors.push(SyntaxError::new(InvalidSuffix, range + literal_range.start()));
35 InvalidSuffix,
36 range + literal_range.start(),
37 ));
38 } 35 }
39 36
40 if len == 0 { 37 if len == 0 {
@@ -184,12 +181,7 @@ mod test {
184 181
185 fn assert_valid_char(literal: &str) { 182 fn assert_valid_char(literal: &str) {
186 let file = build_file(literal); 183 let file = build_file(literal);
187 assert!( 184 assert!(file.errors().len() == 0, "Errors for literal '{}': {:?}", literal, file.errors());
188 file.errors().len() == 0,
189 "Errors for literal '{}': {:?}",
190 literal,
191 file.errors()
192 );
193 } 185 }
194 186
195 fn assert_invalid_char(literal: &str) { 187 fn assert_invalid_char(literal: &str) {
@@ -258,13 +250,7 @@ mod test {
258 250
259 #[test] 251 #[test]
260 fn test_valid_unicode_escape() { 252 fn test_valid_unicode_escape() {
261 let valid = [ 253 let valid = [r"\u{FF}", r"\u{0}", r"\u{F}", r"\u{10FFFF}", r"\u{1_0__FF___FF_____}"];
262 r"\u{FF}",
263 r"\u{0}",
264 r"\u{F}",
265 r"\u{10FFFF}",
266 r"\u{1_0__FF___FF_____}",
267 ];
268 for c in &valid { 254 for c in &valid {
269 assert_valid_char(c); 255 assert_valid_char(c);
270 } 256 }
diff --git a/crates/ra_syntax/src/validation/string.rs b/crates/ra_syntax/src/validation/string.rs
index 365fe8d2d..4fd7fffdf 100644
--- a/crates/ra_syntax/src/validation/string.rs
+++ b/crates/ra_syntax/src/validation/string.rs
@@ -29,10 +29,7 @@ pub(crate) fn validate_string_node(node: &ast::String, errors: &mut Vec<SyntaxEr
29 } 29 }
30 30
31 if let Some(range) = components.suffix { 31 if let Some(range) = components.suffix {
32 errors.push(SyntaxError::new( 32 errors.push(SyntaxError::new(InvalidSuffix, range + literal_range.start()));
33 InvalidSuffix,
34 range + literal_range.start(),
35 ));
36 } 33 }
37} 34}
38 35
@@ -48,12 +45,7 @@ mod test {
48 45
49 fn assert_valid_str(literal: &str) { 46 fn assert_valid_str(literal: &str) {
50 let file = build_file(literal); 47 let file = build_file(literal);
51 assert!( 48 assert!(file.errors().len() == 0, "Errors for literal '{}': {:?}", literal, file.errors());
52 file.errors().len() == 0,
53 "Errors for literal '{}': {:?}",
54 literal,
55 file.errors()
56 );
57 } 49 }
58 50
59 fn assert_invalid_str(literal: &str) { 51 fn assert_invalid_str(literal: &str) {
@@ -121,13 +113,7 @@ mod test {
121 113
122 #[test] 114 #[test]
123 fn test_valid_unicode_escape() { 115 fn test_valid_unicode_escape() {
124 let valid = [ 116 let valid = [r"\u{FF}", r"\u{0}", r"\u{F}", r"\u{10FFFF}", r"\u{1_0__FF___FF_____}"];
125 r"\u{FF}",
126 r"\u{0}",
127 r"\u{F}",
128 r"\u{10FFFF}",
129 r"\u{1_0__FF___FF_____}",
130 ];
131 for c in &valid { 117 for c in &valid {
132 assert_valid_str(c); 118 assert_valid_str(c);
133 } 119 }
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs
index 37ae6329b..e8b9112d4 100644
--- a/crates/ra_syntax/src/yellow/builder.rs
+++ b/crates/ra_syntax/src/yellow/builder.rs
@@ -12,10 +12,7 @@ pub(crate) struct GreenBuilder {
12 12
13impl GreenBuilder { 13impl GreenBuilder {
14 pub(crate) fn new() -> GreenBuilder { 14 pub(crate) fn new() -> GreenBuilder {
15 GreenBuilder { 15 GreenBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() }
16 errors: Vec::new(),
17 inner: GreenNodeBuilder::new(),
18 }
19 } 16 }
20} 17}
21 18
diff --git a/crates/ra_syntax/src/yellow/syntax_error.rs b/crates/ra_syntax/src/yellow/syntax_error.rs
index c52c44cc3..412cf82cc 100644
--- a/crates/ra_syntax/src/yellow/syntax_error.rs
+++ b/crates/ra_syntax/src/yellow/syntax_error.rs
@@ -28,10 +28,7 @@ impl Into<Location> for TextRange {
28 28
29impl SyntaxError { 29impl SyntaxError {
30 pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError { 30 pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError {
31 SyntaxError { 31 SyntaxError { kind, location: loc.into() }
32 kind,
33 location: loc.into(),
34 }
35 } 32 }
36 33
37 pub fn kind(&self) -> SyntaxErrorKind { 34 pub fn kind(&self) -> SyntaxErrorKind {
@@ -119,10 +116,9 @@ impl fmt::Display for SyntaxErrorKind {
119 InvalidByteEscape => write!(f, "Invalid escape sequence"), 116 InvalidByteEscape => write!(f, "Invalid escape sequence"),
120 TooShortByteCodeEscape => write!(f, "Escape sequence should have two digits"), 117 TooShortByteCodeEscape => write!(f, "Escape sequence should have two digits"),
121 MalformedByteCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"), 118 MalformedByteCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"),
122 UnicodeEscapeForbidden => write!( 119 UnicodeEscapeForbidden => {
123 f, 120 write!(f, "Unicode escapes are not allowed in byte literals or byte strings")
124 "Unicode escapes are not allowed in byte literals or byte strings" 121 }
125 ),
126 TooShortAsciiCodeEscape => write!(f, "Escape sequence should have two digits"), 122 TooShortAsciiCodeEscape => write!(f, "Escape sequence should have two digits"),
127 AsciiCodeEscapeOutOfRange => { 123 AsciiCodeEscapeOutOfRange => {
128 write!(f, "Escape sequence should be between \\x00 and \\x7F") 124 write!(f, "Escape sequence should be between \\x00 and \\x7F")
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs
index 378cd1b2e..84e5b231a 100644
--- a/crates/ra_syntax/src/yellow/syntax_text.rs
+++ b/crates/ra_syntax/src/yellow/syntax_text.rs
@@ -10,10 +10,7 @@ pub struct SyntaxText<'a> {
10 10
11impl<'a> SyntaxText<'a> { 11impl<'a> SyntaxText<'a> {
12 pub(crate) fn new(node: &'a SyntaxNode) -> SyntaxText<'a> { 12 pub(crate) fn new(node: &'a SyntaxNode) -> SyntaxText<'a> {
13 SyntaxText { 13 SyntaxText { node, range: node.range() }
14 node,
15 range: node.range(),
16 }
17 } 14 }
18 15
19 pub fn chunks(&self) -> impl Iterator<Item = &'a str> { 16 pub fn chunks(&self) -> impl Iterator<Item = &'a str> {
@@ -58,10 +55,7 @@ impl<'a> SyntaxText<'a> {
58 let range = range.restrict(self.range).unwrap_or_else(|| { 55 let range = range.restrict(self.range).unwrap_or_else(|| {
59 panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) 56 panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range)
60 }); 57 });
61 SyntaxText { 58 SyntaxText { node: self.node, range }
62 node: self.node,
63 range,
64 }
65 } 59 }
66 60
67 pub fn char_at(&self, offset: impl Into<TextUnit>) -> Option<char> { 61 pub fn char_at(&self, offset: impl Into<TextUnit>) -> Option<char> {
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs
index 3243b27ae..168d0623d 100644
--- a/crates/ra_syntax/tests/test.rs
+++ b/crates/ra_syntax/tests/test.rs
@@ -23,36 +23,28 @@ fn lexer_tests() {
23 23
24#[test] 24#[test]
25fn parser_tests() { 25fn parser_tests() {
26 dir_tests( 26 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| {
27 &test_data_dir(), 27 let file = SourceFile::parse(text);
28 &["parser/inline/ok", "parser/ok"], 28 let errors = file.errors();
29 |text, path| { 29 assert_eq!(
30 let file = SourceFile::parse(text); 30 &*errors,
31 let errors = file.errors(); 31 &[] as &[ra_syntax::SyntaxError],
32 assert_eq!( 32 "There should be no errors in the file {:?}",
33 &*errors, 33 path.display()
34 &[] as &[ra_syntax::SyntaxError], 34 );
35 "There should be no errors in the file {:?}", 35 dump_tree(file.syntax())
36 path.display() 36 });
37 ); 37 dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], |text, path| {
38 dump_tree(file.syntax()) 38 let file = SourceFile::parse(text);
39 }, 39 let errors = file.errors();
40 ); 40 assert_ne!(
41 dir_tests( 41 &*errors,
42 &test_data_dir(), 42 &[] as &[ra_syntax::SyntaxError],
43 &["parser/err", "parser/inline/err"], 43 "There should be errors in the file {:?}",
44 |text, path| { 44 path.display()
45 let file = SourceFile::parse(text); 45 );
46 let errors = file.errors(); 46 dump_tree(file.syntax())
47 assert_ne!( 47 });
48 &*errors,
49 &[] as &[ra_syntax::SyntaxError],
50 "There should be errors in the file {:?}",
51 path.display()
52 );
53 dump_tree(file.syntax())
54 },
55 );
56} 48}
57 49
58#[test] 50#[test]
@@ -87,12 +79,7 @@ fn self_hosting_parsing() {
87 let text = read_text(entry.path()); 79 let text = read_text(entry.path());
88 let node = SourceFile::parse(&text); 80 let node = SourceFile::parse(&text);
89 let errors = node.errors(); 81 let errors = node.errors();
90 assert_eq!( 82 assert_eq!(&*errors, &[], "There should be no errors in the file {:?}", entry);
91 &*errors,
92 &[],
93 "There should be no errors in the file {:?}",
94 entry
95 );
96 } 83 }
97 assert!( 84 assert!(
98 count > 30, 85 count > 30,
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
index fb693b3ae..df673ba18 100644
--- a/crates/ra_text_edit/src/lib.rs
+++ b/crates/ra_text_edit/src/lib.rs
@@ -15,10 +15,7 @@ pub struct AtomTextEdit {
15 15
16impl AtomTextEdit { 16impl AtomTextEdit {
17 pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit { 17 pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit {
18 AtomTextEdit { 18 AtomTextEdit { delete: range, insert: replace_with }
19 delete: range,
20 insert: replace_with,
21 }
22 } 19 }
23 20
24 pub fn delete(range: TextRange) -> AtomTextEdit { 21 pub fn delete(range: TextRange) -> AtomTextEdit {
diff --git a/crates/ra_text_edit/src/test_utils.rs b/crates/ra_text_edit/src/test_utils.rs
index 745f21c93..9e21b24f6 100644
--- a/crates/ra_text_edit/src/test_utils.rs
+++ b/crates/ra_text_edit/src/test_utils.rs
@@ -8,9 +8,7 @@ pub fn arb_text() -> proptest::string::RegexGeneratorStrategy<String> {
8} 8}
9 9
10fn text_offsets(text: &str) -> Vec<TextUnit> { 10fn text_offsets(text: &str) -> Vec<TextUnit> {
11 text.char_indices() 11 text.char_indices().map(|(i, _)| TextUnit::from_usize(i)).collect()
12 .map(|(i, _)| TextUnit::from_usize(i))
13 .collect()
14} 12}
15 13
16pub fn arb_offset(text: &str) -> BoxedStrategy<TextUnit> { 14pub fn arb_offset(text: &str) -> BoxedStrategy<TextUnit> {
@@ -56,9 +54,7 @@ pub fn arb_text_edit(text: &str) -> BoxedStrategy<TextEdit> {
56 ) 54 )
57 .boxed() 55 .boxed()
58 } 56 }
59 &[x] => arb_text() 57 &[x] => arb_text().prop_map(move |text| AtomTextEdit::insert(x, text)).boxed(),
60 .prop_map(move |text| AtomTextEdit::insert(x, text))
61 .boxed(),
62 _ => unreachable!(), 58 _ => unreachable!(),
63 }) 59 })
64 .collect(); 60 .collect();
diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs
index 363b3d8c0..8522f99bd 100644
--- a/crates/ra_text_edit/src/text_edit.rs
+++ b/crates/ra_text_edit/src/text_edit.rs
@@ -25,9 +25,7 @@ impl TextEditBuilder {
25 TextEdit::from_atoms(self.atoms) 25 TextEdit::from_atoms(self.atoms)
26 } 26 }
27 pub fn invalidates_offset(&self, offset: TextUnit) -> bool { 27 pub fn invalidates_offset(&self, offset: TextUnit) -> bool {
28 self.atoms 28 self.atoms.iter().any(|atom| atom.delete.contains_inclusive(offset))
29 .iter()
30 .any(|atom| atom.delete.contains_inclusive(offset))
31 } 29 }
32} 30}
33 31
diff --git a/crates/ra_vfs/src/io.rs b/crates/ra_vfs/src/io.rs
index d764c534a..ff5ae3a19 100644
--- a/crates/ra_vfs/src/io.rs
+++ b/crates/ra_vfs/src/io.rs
@@ -14,32 +14,15 @@ use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as _Watc
14use crate::{RootConfig, Roots, VfsRoot}; 14use crate::{RootConfig, Roots, VfsRoot};
15 15
16pub(crate) enum Task { 16pub(crate) enum Task {
17 AddRoot { 17 AddRoot { root: VfsRoot, config: Arc<RootConfig> },
18 root: VfsRoot,
19 config: Arc<RootConfig>,
20 },
21} 18}
22 19
23#[derive(Debug)] 20#[derive(Debug)]
24pub enum TaskResult { 21pub enum TaskResult {
25 BulkLoadRoot { 22 BulkLoadRoot { root: VfsRoot, files: Vec<(RelativePathBuf, String)> },
26 root: VfsRoot, 23 AddSingleFile { root: VfsRoot, path: RelativePathBuf, text: String },
27 files: Vec<(RelativePathBuf, String)>, 24 ChangeSingleFile { root: VfsRoot, path: RelativePathBuf, text: String },
28 }, 25 RemoveSingleFile { root: VfsRoot, path: RelativePathBuf },
29 AddSingleFile {
30 root: VfsRoot,
31 path: RelativePathBuf,
32 text: String,
33 },
34 ChangeSingleFile {
35 root: VfsRoot,
36 path: RelativePathBuf,
37 text: String,
38 },
39 RemoveSingleFile {
40 root: VfsRoot,
41 path: RelativePathBuf,
42 },
43} 26}
44 27
45#[derive(Debug)] 28#[derive(Debug)]
@@ -127,10 +110,7 @@ impl Worker {
127 }, 110 },
128 ); 111 );
129 112
130 Worker { 113 Worker { worker, worker_handle }
131 worker,
132 worker_handle,
133 }
134 } 114 }
135 115
136 pub(crate) fn sender(&self) -> &Sender<Task> { 116 pub(crate) fn sender(&self) -> &Sender<Task> {
@@ -162,9 +142,7 @@ fn watch_root(
162 Some((path, text)) 142 Some((path, text))
163 }) 143 })
164 .collect(); 144 .collect();
165 sender 145 sender.send(TaskResult::BulkLoadRoot { root, files }).unwrap();
166 .send(TaskResult::BulkLoadRoot { root, files })
167 .unwrap();
168 log::debug!("... loaded {}", config.root.as_path().display()); 146 log::debug!("... loaded {}", config.root.as_path().display());
169} 147}
170 148
@@ -233,21 +211,12 @@ fn handle_change(
233 } 211 }
234 ChangeKind::Write => { 212 ChangeKind::Write => {
235 if let Some(text) = read_to_string(&path) { 213 if let Some(text) = read_to_string(&path) {
236 sender 214 sender.send(TaskResult::ChangeSingleFile { root, path: rel_path, text }).unwrap();
237 .send(TaskResult::ChangeSingleFile {
238 root,
239 path: rel_path,
240 text,
241 })
242 .unwrap();
243 } 215 }
244 } 216 }
245 ChangeKind::Remove => sender 217 ChangeKind::Remove => {
246 .send(TaskResult::RemoveSingleFile { 218 sender.send(TaskResult::RemoveSingleFile { root, path: rel_path }).unwrap()
247 root, 219 }
248 path: rel_path,
249 })
250 .unwrap(),
251 } 220 }
252} 221}
253 222
@@ -282,7 +251,5 @@ fn watch_one(watcher: &mut RecommendedWatcher, dir: &Path) {
282} 251}
283 252
284fn read_to_string(path: &Path) -> Option<String> { 253fn read_to_string(path: &Path) -> Option<String> {
285 fs::read_to_string(&path) 254 fs::read_to_string(&path).map_err(|e| log::warn!("failed to read file {}", e)).ok()
286 .map_err(|e| log::warn!("failed to read file {}", e))
287 .ok()
288} 255}
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs
index 71a3f807d..6b4eb6842 100644
--- a/crates/ra_vfs/src/lib.rs
+++ b/crates/ra_vfs/src/lib.rs
@@ -58,10 +58,7 @@ impl std::ops::Deref for Roots {
58 58
59impl RootConfig { 59impl RootConfig {
60 fn new(root: PathBuf, excluded_dirs: Vec<PathBuf>) -> RootConfig { 60 fn new(root: PathBuf, excluded_dirs: Vec<PathBuf>) -> RootConfig {
61 RootConfig { 61 RootConfig { root, excluded_dirs }
62 root,
63 excluded_dirs,
64 }
65 } 62 }
66 /// Cheks if root contains a path and returns a root-relative path. 63 /// Cheks if root contains a path and returns a root-relative path.
67 pub(crate) fn contains(&self, path: &Path) -> Option<RelativePathBuf> { 64 pub(crate) fn contains(&self, path: &Path) -> Option<RelativePathBuf> {
@@ -111,9 +108,7 @@ impl Roots {
111 Roots { roots } 108 Roots { roots }
112 } 109 }
113 pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> { 110 pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> {
114 self.roots 111 self.roots.iter().find_map(|(root, data)| data.contains(path).map(|it| (root, it)))
115 .iter()
116 .find_map(|(root, data)| data.contains(path).map(|it| (root, it)))
117 } 112 }
118} 113}
119 114
@@ -154,21 +149,10 @@ impl Vfs {
154 149
155 for (root, config) in roots.iter() { 150 for (root, config) in roots.iter() {
156 root2files.insert(root, Default::default()); 151 root2files.insert(root, Default::default());
157 worker 152 worker.sender().send(io::Task::AddRoot { root, config: Arc::clone(config) }).unwrap();
158 .sender()
159 .send(io::Task::AddRoot {
160 root,
161 config: Arc::clone(config),
162 })
163 .unwrap();
164 } 153 }
165 let res = Vfs { 154 let res =
166 roots, 155 Vfs { roots, files: Arena::default(), root2files, worker, pending_changes: Vec::new() };
167 files: Arena::default(),
168 root2files,
169 worker,
170 pending_changes: Vec::new(),
171 };
172 let vfs_roots = res.roots.iter().map(|(id, _)| id).collect(); 156 let vfs_roots = res.roots.iter().map(|(id, _)| id).collect();
173 (res, vfs_roots) 157 (res, vfs_roots)
174 } 158 }
@@ -205,12 +189,7 @@ impl Vfs {
205 let text = fs::read_to_string(path).unwrap_or_default(); 189 let text = fs::read_to_string(path).unwrap_or_default();
206 let text = Arc::new(text); 190 let text = Arc::new(text);
207 let file = self.add_file(root, rel_path.clone(), Arc::clone(&text), false); 191 let file = self.add_file(root, rel_path.clone(), Arc::clone(&text), false);
208 let change = VfsChange::AddFile { 192 let change = VfsChange::AddFile { file, text, root, path: rel_path };
209 file,
210 text,
211 root,
212 path: rel_path,
213 };
214 self.pending_changes.push(change); 193 self.pending_changes.push(change);
215 Some(file) 194 Some(file)
216 }; 195 };
@@ -243,10 +222,7 @@ impl Vfs {
243 cur_files.push((file, path, text)); 222 cur_files.push((file, path, text));
244 } 223 }
245 224
246 let change = VfsChange::AddRoot { 225 let change = VfsChange::AddRoot { root, files: cur_files };
247 root,
248 files: cur_files,
249 };
250 self.pending_changes.push(change); 226 self.pending_changes.push(change);
251 } 227 }
252 TaskResult::AddSingleFile { root, path, text } => { 228 TaskResult::AddSingleFile { root, path, text } => {
@@ -278,12 +254,7 @@ impl Vfs {
278 ) -> Option<VfsFile> { 254 ) -> Option<VfsFile> {
279 let text = Arc::new(text); 255 let text = Arc::new(text);
280 let file = self.add_file(root, path.clone(), text.clone(), is_overlay); 256 let file = self.add_file(root, path.clone(), text.clone(), is_overlay);
281 self.pending_changes.push(VfsChange::AddFile { 257 self.pending_changes.push(VfsChange::AddFile { file, root, path, text });
282 file,
283 root,
284 path,
285 text,
286 });
287 Some(file) 258 Some(file)
288 } 259 }
289 260
@@ -293,8 +264,7 @@ impl Vfs {
293 } 264 }
294 let text = Arc::new(text); 265 let text = Arc::new(text);
295 self.change_file(file, text.clone(), is_overlay); 266 self.change_file(file, text.clone(), is_overlay);
296 self.pending_changes 267 self.pending_changes.push(VfsChange::ChangeFile { file, text });
297 .push(VfsChange::ChangeFile { file, text });
298 } 268 }
299 269
300 fn do_remove_file( 270 fn do_remove_file(
@@ -308,8 +278,7 @@ impl Vfs {
308 return; 278 return;
309 } 279 }
310 self.remove_file(file); 280 self.remove_file(file);
311 self.pending_changes 281 self.pending_changes.push(VfsChange::RemoveFile { root, path, file });
312 .push(VfsChange::RemoveFile { root, path, file });
313 } 282 }
314 283
315 pub fn add_file_overlay(&mut self, path: &Path, text: String) -> Option<VfsFile> { 284 pub fn add_file_overlay(&mut self, path: &Path, text: String) -> Option<VfsFile> {
@@ -363,12 +332,7 @@ impl Vfs {
363 text: Arc<String>, 332 text: Arc<String>,
364 is_overlayed: bool, 333 is_overlayed: bool,
365 ) -> VfsFile { 334 ) -> VfsFile {
366 let data = VfsFileData { 335 let data = VfsFileData { root, path, text, is_overlayed };
367 root,
368 path,
369 text,
370 is_overlayed,
371 };
372 let file = self.files.alloc(data); 336 let file = self.files.alloc(data);
373 self.root2files.get_mut(root).unwrap().insert(file); 337 self.root2files.get_mut(root).unwrap().insert(file);
374 file 338 file
@@ -396,32 +360,14 @@ impl Vfs {
396 } 360 }
397 361
398 fn find_file(&self, root: VfsRoot, path: &RelativePath) -> Option<VfsFile> { 362 fn find_file(&self, root: VfsRoot, path: &RelativePath) -> Option<VfsFile> {
399 self.root2files[root] 363 self.root2files[root].iter().map(|&it| it).find(|&file| self.files[file].path == path)
400 .iter()
401 .map(|&it| it)
402 .find(|&file| self.files[file].path == path)
403 } 364 }
404} 365}
405 366
406#[derive(Debug, Clone)] 367#[derive(Debug, Clone)]
407pub enum VfsChange { 368pub enum VfsChange {
408 AddRoot { 369 AddRoot { root: VfsRoot, files: Vec<(VfsFile, RelativePathBuf, Arc<String>)> },
409 root: VfsRoot, 370 AddFile { root: VfsRoot, file: VfsFile, path: RelativePathBuf, text: Arc<String> },
410 files: Vec<(VfsFile, RelativePathBuf, Arc<String>)>, 371 RemoveFile { root: VfsRoot, file: VfsFile, path: RelativePathBuf },
411 }, 372 ChangeFile { file: VfsFile, text: Arc<String> },
412 AddFile {
413 root: VfsRoot,
414 file: VfsFile,
415 path: RelativePathBuf,
416 text: Arc<String>,
417 },
418 RemoveFile {
419 root: VfsRoot,
420 file: VfsFile,
421 path: RelativePathBuf,
422 },
423 ChangeFile {
424 file: VfsFile,
425 text: Arc<String>,
426 },
427} 373}
diff --git a/crates/ra_vfs/tests/vfs.rs b/crates/ra_vfs/tests/vfs.rs
index 545e1dbdd..649ef96c9 100644
--- a/crates/ra_vfs/tests/vfs.rs
+++ b/crates/ra_vfs/tests/vfs.rs
@@ -7,10 +7,7 @@ use tempfile::tempdir;
7 7
8fn process_tasks(vfs: &mut Vfs, num_tasks: u32) { 8fn process_tasks(vfs: &mut Vfs, num_tasks: u32) {
9 for _ in 0..num_tasks { 9 for _ in 0..num_tasks {
10 let task = vfs 10 let task = vfs.task_receiver().recv_timeout(Duration::from_secs(3)).unwrap();
11 .task_receiver()
12 .recv_timeout(Duration::from_secs(3))
13 .unwrap();
14 log::debug!("{:?}", task); 11 log::debug!("{:?}", task);
15 vfs.handle_task(task); 12 vfs.handle_task(task);
16 } 13 }
@@ -32,11 +29,7 @@ macro_rules! assert_match {
32fn test_vfs_works() -> std::io::Result<()> { 29fn test_vfs_works() -> std::io::Result<()> {
33 // Logger::with_str("vfs=debug,ra_vfs=debug").start().unwrap(); 30 // Logger::with_str("vfs=debug,ra_vfs=debug").start().unwrap();
34 31
35 let files = [ 32 let files = [("a/foo.rs", "hello"), ("a/bar.rs", "world"), ("a/b/baz.rs", "nested hello")];
36 ("a/foo.rs", "hello"),
37 ("a/bar.rs", "world"),
38 ("a/b/baz.rs", "nested hello"),
39 ];
40 33
41 let dir = tempdir().unwrap(); 34 let dir = tempdir().unwrap();
42 for (path, text) in files.iter() { 35 for (path, text) in files.iter() {
@@ -66,14 +59,10 @@ fn test_vfs_works() -> std::io::Result<()> {
66 }) 59 })
67 .collect::<HashSet<_>>(); 60 .collect::<HashSet<_>>();
68 61
69 let expected_files = [ 62 let expected_files = [("foo.rs", "hello"), ("bar.rs", "world"), ("baz.rs", "nested hello")]
70 ("foo.rs", "hello"), 63 .iter()
71 ("bar.rs", "world"), 64 .map(|(path, text)| (path.to_string(), text.to_string()))
72 ("baz.rs", "nested hello"), 65 .collect::<HashSet<_>>();
73 ]
74 .iter()
75 .map(|(path, text)| (path.to_string(), text.to_string()))
76 .collect::<HashSet<_>>();
77 66
78 assert_eq!(files, expected_files); 67 assert_eq!(files, expected_files);
79 } 68 }
@@ -107,14 +96,10 @@ fn test_vfs_works() -> std::io::Result<()> {
107 ); 96 );
108 97
109 vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string()); 98 vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string());
110 assert_match!( 99 assert_match!(vfs.commit_changes().as_slice(), [VfsChange::AddFile { text, path, .. }], {
111 vfs.commit_changes().as_slice(), 100 assert_eq!(text.as_str(), "spam");
112 [VfsChange::AddFile { text, path, .. }], 101 assert_eq!(path, "spam.rs");
113 { 102 });
114 assert_eq!(text.as_str(), "spam");
115 assert_eq!(path, "spam.rs");
116 }
117 );
118 103
119 vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs")); 104 vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs"));
120 assert_match!( 105 assert_match!(
@@ -126,30 +111,17 @@ fn test_vfs_works() -> std::io::Result<()> {
126 fs::create_dir_all(dir.path().join("a/sub1/sub2")).unwrap(); 111 fs::create_dir_all(dir.path().join("a/sub1/sub2")).unwrap();
127 fs::write(dir.path().join("a/sub1/sub2/new.rs"), "new hello").unwrap(); 112 fs::write(dir.path().join("a/sub1/sub2/new.rs"), "new hello").unwrap();
128 process_tasks(&mut vfs, 1); 113 process_tasks(&mut vfs, 1);
129 assert_match!( 114 assert_match!(vfs.commit_changes().as_slice(), [VfsChange::AddFile { text, path, .. }], {
130 vfs.commit_changes().as_slice(), 115 assert_eq!(text.as_str(), "new hello");
131 [VfsChange::AddFile { text, path, .. }], 116 assert_eq!(path, "sub1/sub2/new.rs");
132 { 117 });
133 assert_eq!(text.as_str(), "new hello");
134 assert_eq!(path, "sub1/sub2/new.rs");
135 }
136 );
137 118
138 fs::rename( 119 fs::rename(&dir.path().join("a/sub1/sub2/new.rs"), &dir.path().join("a/sub1/sub2/new1.rs"))
139 &dir.path().join("a/sub1/sub2/new.rs"), 120 .unwrap();
140 &dir.path().join("a/sub1/sub2/new1.rs"),
141 )
142 .unwrap();
143 process_tasks(&mut vfs, 2); 121 process_tasks(&mut vfs, 2);
144 assert_match!( 122 assert_match!(
145 vfs.commit_changes().as_slice(), 123 vfs.commit_changes().as_slice(),
146 [VfsChange::RemoveFile { 124 [VfsChange::RemoveFile { path: removed_path, .. }, VfsChange::AddFile { text, path: added_path, .. }],
147 path: removed_path, ..
148 }, VfsChange::AddFile {
149 text,
150 path: added_path,
151 ..
152 }],
153 { 125 {
154 assert_eq!(removed_path, "sub1/sub2/new.rs"); 126 assert_eq!(removed_path, "sub1/sub2/new.rs");
155 assert_eq!(added_path, "sub1/sub2/new1.rs"); 127 assert_eq!(added_path, "sub1/sub2/new1.rs");
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 35a679aea..09fc2e659 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -85,9 +85,7 @@ pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) {
85 stack.push(from); 85 stack.push(from);
86 } else if text.starts_with(&close) { 86 } else if text.starts_with(&close) {
87 text = &text[close.len()..]; 87 text = &text[close.len()..];
88 let from = stack 88 let from = stack.pop().unwrap_or_else(|| panic!("unmatched </{}>", tag));
89 .pop()
90 .unwrap_or_else(|| panic!("unmatched </{}>", tag));
91 let to = TextUnit::of_str(&res); 89 let to = TextUnit::of_str(&res);
92 ranges.push(TextRange::from_to(from, to)); 90 ranges.push(TextRange::from_to(from, to));
93 } 91 }
@@ -131,10 +129,7 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> {
131 macro_rules! flush { 129 macro_rules! flush {
132 () => { 130 () => {
133 if let Some(meta) = meta { 131 if let Some(meta) = meta {
134 res.push(FixtureEntry { 132 res.push(FixtureEntry { meta: meta.to_string(), text: buf.clone() });
135 meta: meta.to_string(),
136 text: buf.clone(),
137 });
138 buf.clear(); 133 buf.clear();
139 } 134 }
140 }; 135 };
@@ -226,15 +221,13 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a
226 let mut l = l.iter().collect::<Vec<_>>(); 221 let mut l = l.iter().collect::<Vec<_>>();
227 let mut r = r.iter().collect::<Vec<_>>(); 222 let mut r = r.iter().collect::<Vec<_>>();
228 223
229 l.retain( 224 l.retain(|l| match r.iter().position(|r| find_mismatch(l, r).is_none()) {
230 |l| match r.iter().position(|r| find_mismatch(l, r).is_none()) { 225 Some(i) => {
231 Some(i) => { 226 r.remove(i);
232 r.remove(i); 227 false
233 false 228 }
234 } 229 None => true,
235 None => true, 230 });
236 },
237 );
238 231
239 if !l.is_empty() { 232 if !l.is_empty() {
240 assert!(!r.is_empty()); 233 assert!(!r.is_empty());
@@ -250,10 +243,7 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a
250 return Some((expected, actual)); 243 return Some((expected, actual));
251 } 244 }
252 245
253 l.values() 246 l.values().zip(r.values()).filter_map(|(l, r)| find_mismatch(l, r)).nth(0)
254 .zip(r.values())
255 .filter_map(|(l, r)| find_mismatch(l, r))
256 .nth(0)
257 } 247 }
258 (&Null, &Null) => None, 248 (&Null, &Null) => None,
259 // magic string literal "{...}" acts as wildcard for any sub-JSON 249 // magic string literal "{...}" acts as wildcard for any sub-JSON
@@ -312,12 +302,7 @@ fn test_from_dir(dir: &Path) -> Vec<PathBuf> {
312 302
313pub fn project_dir() -> PathBuf { 303pub fn project_dir() -> PathBuf {
314 let dir = env!("CARGO_MANIFEST_DIR"); 304 let dir = env!("CARGO_MANIFEST_DIR");
315 PathBuf::from(dir) 305 PathBuf::from(dir).parent().unwrap().parent().unwrap().to_owned()
316 .parent()
317 .unwrap()
318 .parent()
319 .unwrap()
320 .to_owned()
321} 306}
322 307
323/// Read file and normalize newlines. 308/// Read file and normalize newlines.
diff --git a/crates/test_utils/src/marks.rs b/crates/test_utils/src/marks.rs
index ee47b5219..d2a84643c 100644
--- a/crates/test_utils/src/marks.rs
+++ b/crates/test_utils/src/marks.rs
@@ -64,10 +64,7 @@ pub struct MarkChecker {
64impl MarkChecker { 64impl MarkChecker {
65 pub fn new(mark: &'static AtomicUsize) -> MarkChecker { 65 pub fn new(mark: &'static AtomicUsize) -> MarkChecker {
66 let value_on_entry = mark.load(Ordering::SeqCst); 66 let value_on_entry = mark.load(Ordering::SeqCst);
67 MarkChecker { 67 MarkChecker { mark, value_on_entry }
68 mark,
69 value_on_entry,
70 }
71 } 68 }
72} 69}
73 70
diff --git a/crates/thread_worker/src/lib.rs b/crates/thread_worker/src/lib.rs
index 5e46f62fe..ca0aad136 100644
--- a/crates/thread_worker/src/lib.rs
+++ b/crates/thread_worker/src/lib.rs
@@ -71,12 +71,5 @@ impl WorkerHandle {
71fn worker_chan<I, O>(buf: usize) -> (Worker<I, O>, Receiver<I>, Sender<O>) { 71fn worker_chan<I, O>(buf: usize) -> (Worker<I, O>, Receiver<I>, Sender<O>) {
72 let (input_sender, input_receiver) = bounded::<I>(buf); 72 let (input_sender, input_receiver) = bounded::<I>(buf);
73 let (output_sender, output_receiver) = unbounded::<O>(); 73 let (output_sender, output_receiver) = unbounded::<O>();
74 ( 74 (Worker { inp: input_sender, out: output_receiver }, input_receiver, output_sender)
75 Worker {
76 inp: input_sender,
77 out: output_receiver,
78 },
79 input_receiver,
80 output_sender,
81 )
82} 75}
diff --git a/crates/tools/src/bin/pre-commit.rs b/crates/tools/src/bin/pre-commit.rs
index e00bd0d3d..ea18c0863 100644
--- a/crates/tools/src/bin/pre-commit.rs
+++ b/crates/tools/src/bin/pre-commit.rs
@@ -19,19 +19,10 @@ fn update_staged() -> Result<()> {
19 .current_dir(&root) 19 .current_dir(&root)
20 .output()?; 20 .output()?;
21 if !output.status.success() { 21 if !output.status.success() {
22 bail!( 22 bail!("`git diff --diff-filter=MAR --name-only --cached` exited with {}", output.status);
23 "`git diff --diff-filter=MAR --name-only --cached` exited with {}",
24 output.status
25 );
26 } 23 }
27 for line in String::from_utf8(output.stdout)?.lines() { 24 for line in String::from_utf8(output.stdout)?.lines() {
28 run( 25 run(&format!("git update-index --add {}", root.join(line).to_string_lossy()), ".")?;
29 &format!(
30 "git update-index --add {}",
31 root.join(line).to_string_lossy()
32 ),
33 ".",
34 )?;
35 } 26 }
36 Ok(()) 27 Ok(())
37} 28}
diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs
index 311bcb4d8..ef9c613a7 100644
--- a/crates/tools/src/lib.rs
+++ b/crates/tools/src/lib.rs
@@ -58,10 +58,8 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> {
58 None => continue 'outer, 58 None => continue 'outer,
59 } 59 }
60 }; 60 };
61 let text: String = itertools::join( 61 let text: String =
62 block.map(|(_, line)| line).chain(::std::iter::once("")), 62 itertools::join(block.map(|(_, line)| line).chain(::std::iter::once("")), "\n");
63 "\n",
64 );
65 assert!(!text.trim().is_empty() && text.ends_with('\n')); 63 assert!(!text.trim().is_empty() && text.ends_with('\n'));
66 res.push((start_line, Test { name, text, ok })) 64 res.push((start_line, Test { name, text, ok }))
67 } 65 }
@@ -78,11 +76,7 @@ pub fn generate(mode: Mode) -> Result<()> {
78} 76}
79 77
80pub fn project_root() -> PathBuf { 78pub fn project_root() -> PathBuf {
81 Path::new(&env!("CARGO_MANIFEST_DIR")) 79 Path::new(&env!("CARGO_MANIFEST_DIR")).ancestors().nth(2).unwrap().to_path_buf()
82 .ancestors()
83 .nth(2)
84 .unwrap()
85 .to_path_buf()
86} 80}
87 81
88pub fn run(cmdline: &str, dir: &str) -> Result<()> { 82pub fn run(cmdline: &str, dir: &str) -> Result<()> {
@@ -90,10 +84,7 @@ pub fn run(cmdline: &str, dir: &str) -> Result<()> {
90 let project_dir = project_root().join(dir); 84 let project_dir = project_root().join(dir);
91 let mut args = cmdline.split_whitespace(); 85 let mut args = cmdline.split_whitespace();
92 let exec = args.next().unwrap(); 86 let exec = args.next().unwrap();
93 let status = Command::new(exec) 87 let status = Command::new(exec).args(args).current_dir(project_dir).status()?;
94 .args(args)
95 .current_dir(project_dir)
96 .status()?;
97 if !status.success() { 88 if !status.success() {
98 bail!("`{}` exited with {}", cmdline, status); 89 bail!("`{}` exited with {}", cmdline, status);
99 } 90 }
@@ -112,10 +103,7 @@ pub fn run_rustfmt(mode: Mode) -> Result<()> {
112 }; 103 };
113 104
114 if mode == Verify { 105 if mode == Verify {
115 run( 106 run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?;
116 &format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN),
117 ".",
118 )?;
119 } else { 107 } else {
120 run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?; 108 run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?;
121 } 109 }
@@ -124,10 +112,7 @@ pub fn run_rustfmt(mode: Mode) -> Result<()> {
124 112
125pub fn install_rustfmt() -> Result<()> { 113pub fn install_rustfmt() -> Result<()> {
126 run(&format!("rustup install {}", TOOLCHAIN), ".")?; 114 run(&format!("rustup install {}", TOOLCHAIN), ".")?;
127 run( 115 run(&format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN), ".")
128 &format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN),
129 ".",
130 )
131} 116}
132 117
133pub fn install_format_hook() -> Result<()> { 118pub fn install_format_hook() -> Result<()> {
@@ -156,10 +141,7 @@ pub fn run_fuzzer() -> Result<()> {
156 _ => run("cargo install cargo-fuzz", ".")?, 141 _ => run("cargo install cargo-fuzz", ".")?,
157 }; 142 };
158 143
159 run( 144 run("rustup run nightly -- cargo fuzz run parser", "./crates/ra_syntax")
160 "rustup run nightly -- cargo fuzz run parser",
161 "./crates/ra_syntax",
162 )
163} 145}
164 146
165pub fn gen_tests(mode: Mode) -> Result<()> { 147pub fn gen_tests(mode: Mode) -> Result<()> {
@@ -245,11 +227,7 @@ fn existing_tests(dir: &Path, ok: bool) -> Result<HashMap<String, (PathBuf, Test
245 file_name[5..file_name.len() - 3].to_string() 227 file_name[5..file_name.len() - 3].to_string()
246 }; 228 };
247 let text = fs::read_to_string(&path)?; 229 let text = fs::read_to_string(&path)?;
248 let test = Test { 230 let test = Test { name: name.clone(), text, ok };
249 name: name.clone(),
250 text,
251 ok,
252 };
253 if let Some(old) = res.insert(name, (path, test)) { 231 if let Some(old) = res.insert(name, (path, test)) {
254 println!("Duplicate test: {:?}", old); 232 println!("Duplicate test: {:?}", old);
255 } 233 }
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs
index c3e293911..963ffbe98 100644
--- a/crates/tools/src/main.rs
+++ b/crates/tools/src/main.rs
@@ -15,10 +15,7 @@ fn main() -> Result<()> {
15 .subcommand(SubCommand::with_name("format-hook")) 15 .subcommand(SubCommand::with_name("format-hook"))
16 .subcommand(SubCommand::with_name("fuzz-tests")) 16 .subcommand(SubCommand::with_name("fuzz-tests"))
17 .get_matches(); 17 .get_matches();
18 match matches 18 match matches.subcommand_name().expect("Subcommand must be specified") {
19 .subcommand_name()
20 .expect("Subcommand must be specified")
21 {
22 "install-code" => install_code_extension()?, 19 "install-code" => install_code_extension()?,
23 "gen-tests" => gen_tests(Overwrite)?, 20 "gen-tests" => gen_tests(Overwrite)?,
24 "gen-syntax" => generate(Overwrite)?, 21 "gen-syntax" => generate(Overwrite)?,
@@ -45,10 +42,7 @@ fn install_code_extension() -> Result<()> {
45 "./editors/code", 42 "./editors/code",
46 )?; 43 )?;
47 } else { 44 } else {
48 run( 45 run(r"code --install-extension ./ra-lsp-0.0.1.vsix --force", "./editors/code")?;
49 r"code --install-extension ./ra-lsp-0.0.1.vsix --force",
50 "./editors/code",
51 )?;
52 } 46 }
53 Ok(()) 47 Ok(())
54} 48}
diff --git a/crates/tools/tests/cli.rs b/crates/tools/tests/cli.rs
index 2ee4b5223..aab52a4aa 100644
--- a/crates/tools/tests/cli.rs
+++ b/crates/tools/tests/cli.rs
@@ -10,19 +10,13 @@ fn generated_grammar_is_fresh() {
10#[test] 10#[test]
11fn generated_tests_are_fresh() { 11fn generated_tests_are_fresh() {
12 if let Err(error) = gen_tests(Verify) { 12 if let Err(error) = gen_tests(Verify) {
13 panic!( 13 panic!("{}. Please update tests by running `cargo gen-tests`", error);
14 "{}. Please update tests by running `cargo gen-tests`",
15 error
16 );
17 } 14 }
18} 15}
19 16
20#[test] 17#[test]
21fn check_code_formatting() { 18fn check_code_formatting() {
22 if let Err(error) = run_rustfmt(Verify) { 19 if let Err(error) = run_rustfmt(Verify) {
23 panic!( 20 panic!("{}. Please format the code by running `cargo format`", error);
24 "{}. Please format the code by running `cargo format`",
25 error
26 );
27 } 21 }
28} 22}