diff options
Diffstat (limited to 'crates')
30 files changed, 765 insertions, 226 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 66cf32524..756acf415 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -96,6 +96,7 @@ mod fill_match_arms; | |||
96 | mod merge_match_arms; | 96 | mod merge_match_arms; |
97 | mod introduce_variable; | 97 | mod introduce_variable; |
98 | mod inline_local_variable; | 98 | mod inline_local_variable; |
99 | mod raw_string; | ||
99 | mod replace_if_let_with_match; | 100 | mod replace_if_let_with_match; |
100 | mod split_import; | 101 | mod split_import; |
101 | mod remove_dbg; | 102 | mod remove_dbg; |
@@ -125,6 +126,10 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis | |||
125 | move_guard::move_guard_to_arm_body, | 126 | move_guard::move_guard_to_arm_body, |
126 | move_guard::move_arm_cond_to_match_guard, | 127 | move_guard::move_arm_cond_to_match_guard, |
127 | move_bounds::move_bounds_to_where_clause, | 128 | move_bounds::move_bounds_to_where_clause, |
129 | raw_string::add_hash, | ||
130 | raw_string::make_raw_string, | ||
131 | raw_string::make_usual_string, | ||
132 | raw_string::remove_hash, | ||
128 | ] | 133 | ] |
129 | } | 134 | } |
130 | 135 | ||
diff --git a/crates/ra_assists/src/raw_string.rs b/crates/ra_assists/src/raw_string.rs new file mode 100644 index 000000000..e00267060 --- /dev/null +++ b/crates/ra_assists/src/raw_string.rs | |||
@@ -0,0 +1,370 @@ | |||
1 | use hir::db::HirDatabase; | ||
2 | use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit}; | ||
3 | |||
4 | use crate::{Assist, AssistCtx, AssistId}; | ||
5 | |||
6 | pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
7 | let literal = ctx.node_at_offset::<Literal>()?; | ||
8 | if literal.token().kind() != ra_syntax::SyntaxKind::STRING { | ||
9 | return None; | ||
10 | } | ||
11 | ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| { | ||
12 | edit.target(literal.syntax().text_range()); | ||
13 | edit.insert(literal.syntax().text_range().start(), "r"); | ||
14 | }); | ||
15 | ctx.build() | ||
16 | } | ||
17 | |||
18 | fn find_usual_string_range(s: &str) -> Option<TextRange> { | ||
19 | Some(TextRange::from_to( | ||
20 | TextUnit::from(s.find('"')? as u32), | ||
21 | TextUnit::from(s.rfind('"')? as u32), | ||
22 | )) | ||
23 | } | ||
24 | |||
25 | pub(crate) fn make_usual_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
26 | let literal = ctx.node_at_offset::<Literal>()?; | ||
27 | if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { | ||
28 | return None; | ||
29 | } | ||
30 | let token = literal.token(); | ||
31 | let text = token.text().as_str(); | ||
32 | let usual_string_range = find_usual_string_range(text)?; | ||
33 | ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| { | ||
34 | edit.target(literal.syntax().text_range()); | ||
35 | // parse inside string to escape `"` | ||
36 | let start_of_inside = usual_string_range.start().to_usize() + 1; | ||
37 | let end_of_inside = usual_string_range.end().to_usize(); | ||
38 | let inside_str = &text[start_of_inside..end_of_inside]; | ||
39 | let escaped = inside_str.escape_default().to_string(); | ||
40 | edit.replace(literal.syntax().text_range(), format!("\"{}\"", escaped)); | ||
41 | }); | ||
42 | ctx.build() | ||
43 | } | ||
44 | |||
45 | pub(crate) fn add_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
46 | let literal = ctx.node_at_offset::<Literal>()?; | ||
47 | if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { | ||
48 | return None; | ||
49 | } | ||
50 | ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| { | ||
51 | edit.target(literal.syntax().text_range()); | ||
52 | edit.insert(literal.syntax().text_range().start() + TextUnit::of_char('r'), "#"); | ||
53 | edit.insert(literal.syntax().text_range().end(), "#"); | ||
54 | }); | ||
55 | ctx.build() | ||
56 | } | ||
57 | |||
58 | pub(crate) fn remove_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
59 | let literal = ctx.node_at_offset::<Literal>()?; | ||
60 | if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { | ||
61 | return None; | ||
62 | } | ||
63 | let token = literal.token(); | ||
64 | let text = token.text().as_str(); | ||
65 | if text.starts_with("r\"") { | ||
66 | // no hash to remove | ||
67 | return None; | ||
68 | } | ||
69 | ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| { | ||
70 | edit.target(literal.syntax().text_range()); | ||
71 | let result = &text[2..text.len() - 1]; | ||
72 | let result = if result.starts_with("\"") { | ||
73 | // no more hash, escape | ||
74 | let internal_str = &result[1..result.len() - 1]; | ||
75 | format!("\"{}\"", internal_str.escape_default().to_string()) | ||
76 | } else { | ||
77 | result.to_owned() | ||
78 | }; | ||
79 | edit.replace(literal.syntax().text_range(), format!("r{}", result)); | ||
80 | }); | ||
81 | ctx.build() | ||
82 | } | ||
83 | |||
84 | #[cfg(test)] | ||
85 | mod test { | ||
86 | use super::*; | ||
87 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
88 | |||
89 | #[test] | ||
90 | fn make_raw_string_target() { | ||
91 | check_assist_target( | ||
92 | make_raw_string, | ||
93 | r#" | ||
94 | fn f() { | ||
95 | let s = <|>"random string"; | ||
96 | } | ||
97 | "#, | ||
98 | r#""random string""#, | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | #[test] | ||
103 | fn make_raw_string_works() { | ||
104 | check_assist( | ||
105 | make_raw_string, | ||
106 | r#" | ||
107 | fn f() { | ||
108 | let s = <|>"random string"; | ||
109 | } | ||
110 | "#, | ||
111 | r#" | ||
112 | fn f() { | ||
113 | let s = <|>r"random string"; | ||
114 | } | ||
115 | "#, | ||
116 | ) | ||
117 | } | ||
118 | |||
119 | #[test] | ||
120 | fn make_raw_string_with_escaped_works() { | ||
121 | check_assist( | ||
122 | make_raw_string, | ||
123 | r#" | ||
124 | fn f() { | ||
125 | let s = <|>"random\nstring"; | ||
126 | } | ||
127 | "#, | ||
128 | r#" | ||
129 | fn f() { | ||
130 | let s = <|>r"random\nstring"; | ||
131 | } | ||
132 | "#, | ||
133 | ) | ||
134 | } | ||
135 | |||
136 | #[test] | ||
137 | fn make_raw_string_not_works() { | ||
138 | check_assist_not_applicable( | ||
139 | make_raw_string, | ||
140 | r#" | ||
141 | fn f() { | ||
142 | let s = <|>r"random string"; | ||
143 | } | ||
144 | "#, | ||
145 | ); | ||
146 | } | ||
147 | |||
148 | #[test] | ||
149 | fn add_hash_target() { | ||
150 | check_assist_target( | ||
151 | add_hash, | ||
152 | r#" | ||
153 | fn f() { | ||
154 | let s = <|>r"random string"; | ||
155 | } | ||
156 | "#, | ||
157 | r#"r"random string""#, | ||
158 | ); | ||
159 | } | ||
160 | |||
161 | #[test] | ||
162 | fn add_hash_works() { | ||
163 | check_assist( | ||
164 | add_hash, | ||
165 | r#" | ||
166 | fn f() { | ||
167 | let s = <|>r"random string"; | ||
168 | } | ||
169 | "#, | ||
170 | r##" | ||
171 | fn f() { | ||
172 | let s = <|>r#"random string"#; | ||
173 | } | ||
174 | "##, | ||
175 | ) | ||
176 | } | ||
177 | |||
178 | #[test] | ||
179 | fn add_more_hash_works() { | ||
180 | check_assist( | ||
181 | add_hash, | ||
182 | r##" | ||
183 | fn f() { | ||
184 | let s = <|>r#"random"string"#; | ||
185 | } | ||
186 | "##, | ||
187 | r###" | ||
188 | fn f() { | ||
189 | let s = <|>r##"random"string"##; | ||
190 | } | ||
191 | "###, | ||
192 | ) | ||
193 | } | ||
194 | |||
195 | #[test] | ||
196 | fn add_hash_not_works() { | ||
197 | check_assist_not_applicable( | ||
198 | add_hash, | ||
199 | r#" | ||
200 | fn f() { | ||
201 | let s = <|>"random string"; | ||
202 | } | ||
203 | "#, | ||
204 | ); | ||
205 | } | ||
206 | |||
207 | #[test] | ||
208 | fn remove_hash_target() { | ||
209 | check_assist_target( | ||
210 | remove_hash, | ||
211 | r##" | ||
212 | fn f() { | ||
213 | let s = <|>r#"random string"#; | ||
214 | } | ||
215 | "##, | ||
216 | r##"r#"random string"#"##, | ||
217 | ); | ||
218 | } | ||
219 | |||
220 | #[test] | ||
221 | fn remove_hash_works() { | ||
222 | check_assist( | ||
223 | remove_hash, | ||
224 | r##" | ||
225 | fn f() { | ||
226 | let s = <|>r#"random string"#; | ||
227 | } | ||
228 | "##, | ||
229 | r#" | ||
230 | fn f() { | ||
231 | let s = <|>r"random string"; | ||
232 | } | ||
233 | "#, | ||
234 | ) | ||
235 | } | ||
236 | |||
237 | #[test] | ||
238 | fn remove_hash_with_quote_works() { | ||
239 | check_assist( | ||
240 | remove_hash, | ||
241 | r##" | ||
242 | fn f() { | ||
243 | let s = <|>r#"random"str"ing"#; | ||
244 | } | ||
245 | "##, | ||
246 | r#" | ||
247 | fn f() { | ||
248 | let s = <|>r"random\"str\"ing"; | ||
249 | } | ||
250 | "#, | ||
251 | ) | ||
252 | } | ||
253 | |||
254 | #[test] | ||
255 | fn remove_more_hash_works() { | ||
256 | check_assist( | ||
257 | remove_hash, | ||
258 | r###" | ||
259 | fn f() { | ||
260 | let s = <|>r##"random string"##; | ||
261 | } | ||
262 | "###, | ||
263 | r##" | ||
264 | fn f() { | ||
265 | let s = <|>r#"random string"#; | ||
266 | } | ||
267 | "##, | ||
268 | ) | ||
269 | } | ||
270 | |||
271 | #[test] | ||
272 | fn remove_hash_not_works() { | ||
273 | check_assist_not_applicable( | ||
274 | remove_hash, | ||
275 | r#" | ||
276 | fn f() { | ||
277 | let s = <|>"random string"; | ||
278 | } | ||
279 | "#, | ||
280 | ); | ||
281 | } | ||
282 | |||
283 | #[test] | ||
284 | fn remove_hash_no_hash_not_works() { | ||
285 | check_assist_not_applicable( | ||
286 | remove_hash, | ||
287 | r#" | ||
288 | fn f() { | ||
289 | let s = <|>r"random string"; | ||
290 | } | ||
291 | "#, | ||
292 | ); | ||
293 | } | ||
294 | |||
295 | #[test] | ||
296 | fn make_usual_string_target() { | ||
297 | check_assist_target( | ||
298 | make_usual_string, | ||
299 | r##" | ||
300 | fn f() { | ||
301 | let s = <|>r#"random string"#; | ||
302 | } | ||
303 | "##, | ||
304 | r##"r#"random string"#"##, | ||
305 | ); | ||
306 | } | ||
307 | |||
308 | #[test] | ||
309 | fn make_usual_string_works() { | ||
310 | check_assist( | ||
311 | make_usual_string, | ||
312 | r##" | ||
313 | fn f() { | ||
314 | let s = <|>r#"random string"#; | ||
315 | } | ||
316 | "##, | ||
317 | r#" | ||
318 | fn f() { | ||
319 | let s = <|>"random string"; | ||
320 | } | ||
321 | "#, | ||
322 | ) | ||
323 | } | ||
324 | |||
325 | #[test] | ||
326 | fn make_usual_string_with_quote_works() { | ||
327 | check_assist( | ||
328 | make_usual_string, | ||
329 | r##" | ||
330 | fn f() { | ||
331 | let s = <|>r#"random"str"ing"#; | ||
332 | } | ||
333 | "##, | ||
334 | r#" | ||
335 | fn f() { | ||
336 | let s = <|>"random\"str\"ing"; | ||
337 | } | ||
338 | "#, | ||
339 | ) | ||
340 | } | ||
341 | |||
342 | #[test] | ||
343 | fn make_usual_string_more_hash_works() { | ||
344 | check_assist( | ||
345 | make_usual_string, | ||
346 | r###" | ||
347 | fn f() { | ||
348 | let s = <|>r##"random string"##; | ||
349 | } | ||
350 | "###, | ||
351 | r##" | ||
352 | fn f() { | ||
353 | let s = <|>"random string"; | ||
354 | } | ||
355 | "##, | ||
356 | ) | ||
357 | } | ||
358 | |||
359 | #[test] | ||
360 | fn make_usual_string_not_works() { | ||
361 | check_assist_not_applicable( | ||
362 | make_usual_string, | ||
363 | r#" | ||
364 | fn f() { | ||
365 | let s = <|>"random string"; | ||
366 | } | ||
367 | "#, | ||
368 | ); | ||
369 | } | ||
370 | } | ||
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 706d24c32..28002f740 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -313,7 +313,7 @@ pub struct StructField { | |||
313 | pub(crate) id: StructFieldId, | 313 | pub(crate) id: StructFieldId, |
314 | } | 314 | } |
315 | 315 | ||
316 | #[derive(Debug)] | 316 | #[derive(Debug, PartialEq, Eq)] |
317 | pub enum FieldSource { | 317 | pub enum FieldSource { |
318 | Named(ast::RecordFieldDef), | 318 | Named(ast::RecordFieldDef), |
319 | Pos(ast::TupleFieldDef), | 319 | Pos(ast::TupleFieldDef), |
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs new file mode 100644 index 000000000..c6ad85fc7 --- /dev/null +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -0,0 +1,211 @@ | |||
1 | use ra_db::{FileId, FilePosition}; | ||
2 | use ra_syntax::{ | ||
3 | algo::find_node_at_offset, | ||
4 | ast::{self, AstNode, NameOwner}, | ||
5 | SyntaxNode, | ||
6 | }; | ||
7 | |||
8 | use crate::{ | ||
9 | db::{AstDatabase, DefDatabase, HirDatabase}, | ||
10 | ids::{AstItemDef, LocationCtx}, | ||
11 | name::AsName, | ||
12 | Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module, | ||
13 | ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, | ||
14 | }; | ||
15 | |||
16 | pub trait FromSource: Sized { | ||
17 | type Ast; | ||
18 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; | ||
19 | } | ||
20 | |||
21 | impl FromSource for Struct { | ||
22 | type Ast = ast::StructDef; | ||
23 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
24 | let id = from_source(db, src)?; | ||
25 | Some(Struct { id }) | ||
26 | } | ||
27 | } | ||
28 | impl FromSource for Union { | ||
29 | type Ast = ast::StructDef; | ||
30 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
31 | let id = from_source(db, src)?; | ||
32 | Some(Union { id }) | ||
33 | } | ||
34 | } | ||
35 | impl FromSource for Enum { | ||
36 | type Ast = ast::EnumDef; | ||
37 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
38 | let id = from_source(db, src)?; | ||
39 | Some(Enum { id }) | ||
40 | } | ||
41 | } | ||
42 | impl FromSource for Trait { | ||
43 | type Ast = ast::TraitDef; | ||
44 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
45 | let id = from_source(db, src)?; | ||
46 | Some(Trait { id }) | ||
47 | } | ||
48 | } | ||
49 | impl FromSource for Function { | ||
50 | type Ast = ast::FnDef; | ||
51 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
52 | let id = from_source(db, src)?; | ||
53 | Some(Function { id }) | ||
54 | } | ||
55 | } | ||
56 | impl FromSource for Const { | ||
57 | type Ast = ast::ConstDef; | ||
58 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
59 | let id = from_source(db, src)?; | ||
60 | Some(Const { id }) | ||
61 | } | ||
62 | } | ||
63 | impl FromSource for Static { | ||
64 | type Ast = ast::StaticDef; | ||
65 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
66 | let id = from_source(db, src)?; | ||
67 | Some(Static { id }) | ||
68 | } | ||
69 | } | ||
70 | impl FromSource for TypeAlias { | ||
71 | type Ast = ast::TypeAliasDef; | ||
72 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
73 | let id = from_source(db, src)?; | ||
74 | Some(TypeAlias { id }) | ||
75 | } | ||
76 | } | ||
77 | // FIXME: add impl FromSource for MacroDef | ||
78 | |||
79 | impl FromSource for ImplBlock { | ||
80 | type Ast = ast::ImplBlock; | ||
81 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
82 | let module_src = crate::ModuleSource::from_child_node( | ||
83 | db, | ||
84 | src.file_id.original_file(db), | ||
85 | &src.ast.syntax(), | ||
86 | ); | ||
87 | let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; | ||
88 | let impls = module.impl_blocks(db); | ||
89 | impls.into_iter().find(|b| b.source(db) == src) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | impl FromSource for EnumVariant { | ||
94 | type Ast = ast::EnumVariant; | ||
95 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
96 | let parent_enum = src.ast.parent_enum(); | ||
97 | let src_enum = Source { file_id: src.file_id, ast: parent_enum }; | ||
98 | let variants = Enum::from_source(db, src_enum)?.variants(db); | ||
99 | variants.into_iter().find(|v| v.source(db) == src) | ||
100 | } | ||
101 | } | ||
102 | |||
103 | impl FromSource for StructField { | ||
104 | type Ast = FieldSource; | ||
105 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
106 | let variant_def: VariantDef = match src.ast { | ||
107 | FieldSource::Named(ref field) => { | ||
108 | let ast = field.syntax().ancestors().find_map(ast::StructDef::cast)?; | ||
109 | let src = Source { file_id: src.file_id, ast }; | ||
110 | let def = Struct::from_source(db, src)?; | ||
111 | VariantDef::from(def) | ||
112 | } | ||
113 | FieldSource::Pos(ref field) => { | ||
114 | let ast = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; | ||
115 | let src = Source { file_id: src.file_id, ast }; | ||
116 | let def = EnumVariant::from_source(db, src)?; | ||
117 | VariantDef::from(def) | ||
118 | } | ||
119 | }; | ||
120 | variant_def | ||
121 | .variant_data(db) | ||
122 | .fields() | ||
123 | .into_iter() | ||
124 | .flat_map(|it| it.iter()) | ||
125 | .map(|(id, _)| StructField { parent: variant_def.clone(), id }) | ||
126 | .find(|f| f.source(db) == src) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | // FIXME: simplify it | ||
131 | impl ModuleSource { | ||
132 | pub fn from_position( | ||
133 | db: &(impl DefDatabase + AstDatabase), | ||
134 | position: FilePosition, | ||
135 | ) -> ModuleSource { | ||
136 | let parse = db.parse(position.file_id); | ||
137 | match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) { | ||
138 | Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), | ||
139 | _ => { | ||
140 | let source_file = parse.tree().to_owned(); | ||
141 | ModuleSource::SourceFile(source_file) | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | pub fn from_child_node( | ||
147 | db: &(impl DefDatabase + AstDatabase), | ||
148 | file_id: FileId, | ||
149 | child: &SyntaxNode, | ||
150 | ) -> ModuleSource { | ||
151 | if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { | ||
152 | ModuleSource::Module(m.clone()) | ||
153 | } else { | ||
154 | let source_file = db.parse(file_id).tree().to_owned(); | ||
155 | ModuleSource::SourceFile(source_file) | ||
156 | } | ||
157 | } | ||
158 | |||
159 | pub fn from_file_id(db: &(impl DefDatabase + AstDatabase), file_id: FileId) -> ModuleSource { | ||
160 | let source_file = db.parse(file_id).tree().to_owned(); | ||
161 | ModuleSource::SourceFile(source_file) | ||
162 | } | ||
163 | } | ||
164 | |||
165 | impl Module { | ||
166 | pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> { | ||
167 | let src_parent = Source { | ||
168 | file_id: src.file_id, | ||
169 | ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), | ||
170 | }; | ||
171 | let parent_module = Module::from_definition(db, src_parent)?; | ||
172 | let child_name = src.ast.name()?; | ||
173 | parent_module.child(db, &child_name.as_name()) | ||
174 | } | ||
175 | |||
176 | pub fn from_definition( | ||
177 | db: &(impl DefDatabase + AstDatabase), | ||
178 | src: Source<ModuleSource>, | ||
179 | ) -> Option<Self> { | ||
180 | let decl_id = match src.ast { | ||
181 | ModuleSource::Module(ref module) => { | ||
182 | assert!(!module.has_semi()); | ||
183 | let ast_id_map = db.ast_id_map(src.file_id); | ||
184 | let item_id = ast_id_map.ast_id(module).with_file_id(src.file_id); | ||
185 | Some(item_id) | ||
186 | } | ||
187 | ModuleSource::SourceFile(_) => None, | ||
188 | }; | ||
189 | |||
190 | let source_root_id = db.file_source_root(src.file_id.original_file(db)); | ||
191 | db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( | ||
192 | |krate| { | ||
193 | let def_map = db.crate_def_map(krate); | ||
194 | let module_id = def_map.find_module_by_source(src.file_id, decl_id)?; | ||
195 | Some(Module { krate, module_id }) | ||
196 | }, | ||
197 | ) | ||
198 | } | ||
199 | } | ||
200 | |||
201 | fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: Source<N>) -> Option<DEF> | ||
202 | where | ||
203 | N: AstNode, | ||
204 | DEF: AstItemDef<N>, | ||
205 | { | ||
206 | let module_src = | ||
207 | crate::ModuleSource::from_child_node(db, src.file_id.original_file(db), &src.ast.syntax()); | ||
208 | let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; | ||
209 | let ctx = LocationCtx::new(db, module, src.file_id); | ||
210 | Some(DEF::from_ast(ctx, &src.ast)) | ||
211 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e7a576aa0..a9de9fb6b 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -53,6 +53,8 @@ pub mod diagnostics; | |||
53 | 53 | ||
54 | mod code_model; | 54 | mod code_model; |
55 | 55 | ||
56 | pub mod from_source; | ||
57 | |||
56 | #[cfg(test)] | 58 | #[cfg(test)] |
57 | mod marks; | 59 | mod marks; |
58 | 60 | ||
@@ -67,6 +69,7 @@ pub use self::{ | |||
67 | adt::VariantDef, | 69 | adt::VariantDef, |
68 | either::Either, | 70 | either::Either, |
69 | expr::ExprScopes, | 71 | expr::ExprScopes, |
72 | from_source::FromSource, | ||
70 | generics::{GenericParam, GenericParams, HasGenericParams}, | 73 | generics::{GenericParam, GenericParams, HasGenericParams}, |
71 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, | 74 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, |
72 | impl_block::ImplBlock, | 75 | impl_block::ImplBlock, |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 8dcea5071..cb405091e 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -93,7 +93,11 @@ impl MockDatabase { | |||
93 | let mut files: Vec<FileId> = self.files.values().copied().collect(); | 93 | let mut files: Vec<FileId> = self.files.values().copied().collect(); |
94 | files.sort(); | 94 | files.sort(); |
95 | for file in files { | 95 | for file in files { |
96 | let module = crate::source_binder::module_from_file_id(self, file).unwrap(); | 96 | let src = crate::Source { |
97 | file_id: file.into(), | ||
98 | ast: crate::ModuleSource::new(self, Some(file), None), | ||
99 | }; | ||
100 | let module = crate::Module::from_definition(self, src).unwrap(); | ||
97 | module.diagnostics( | 101 | module.diagnostics( |
98 | self, | 102 | self, |
99 | &mut DiagnosticSink::new(|d| { | 103 | &mut DiagnosticSink::new(|d| { |
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs index bc721f6e0..c41862a0b 100644 --- a/crates/ra_hir/src/nameres/tests/incremental.rs +++ b/crates/ra_hir/src/nameres/tests/incremental.rs | |||
@@ -114,7 +114,11 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
114 | ); | 114 | ); |
115 | { | 115 | { |
116 | let events = db.log_executed(|| { | 116 | let events = db.log_executed(|| { |
117 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); | 117 | let src = crate::Source { |
118 | file_id: pos.file_id.into(), | ||
119 | ast: crate::ModuleSource::new(&db, Some(pos.file_id), None), | ||
120 | }; | ||
121 | let module = crate::Module::from_definition(&db, src).unwrap(); | ||
118 | let decls = module.declarations(&db); | 122 | let decls = module.declarations(&db); |
119 | assert_eq!(decls.len(), 18); | 123 | assert_eq!(decls.len(), 18); |
120 | }); | 124 | }); |
@@ -124,7 +128,11 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
124 | 128 | ||
125 | { | 129 | { |
126 | let events = db.log_executed(|| { | 130 | let events = db.log_executed(|| { |
127 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); | 131 | let src = crate::Source { |
132 | file_id: pos.file_id.into(), | ||
133 | ast: crate::ModuleSource::new(&db, Some(pos.file_id), None), | ||
134 | }; | ||
135 | let module = crate::Module::from_definition(&db, src).unwrap(); | ||
128 | let decls = module.declarations(&db); | 136 | let decls = module.declarations(&db); |
129 | assert_eq!(decls.len(), 18); | 137 | assert_eq!(decls.len(), 18); |
130 | }); | 138 | }); |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 4d895f0a1..296acc364 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -7,10 +7,9 @@ | |||
7 | /// purely for "IDE needs". | 7 | /// purely for "IDE needs". |
8 | use std::sync::Arc; | 8 | use std::sync::Arc; |
9 | 9 | ||
10 | use ra_db::{FileId, FilePosition}; | 10 | use ra_db::FileId; |
11 | use ra_syntax::{ | 11 | use ra_syntax::{ |
12 | algo::find_node_at_offset, | 12 | ast::{self, AstNode}, |
13 | ast::{self, AstNode, NameOwner}, | ||
14 | AstPtr, | 13 | AstPtr, |
15 | SyntaxKind::*, | 14 | SyntaxKind::*, |
16 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 15 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, |
@@ -28,119 +27,28 @@ use crate::{ | |||
28 | path::known, | 27 | path::known, |
29 | resolve::{ScopeDef, TypeNs, ValueNs}, | 28 | resolve::{ScopeDef, TypeNs, ValueNs}, |
30 | ty::method_resolution::implements_trait, | 29 | ty::method_resolution::implements_trait, |
31 | AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef, | 30 | AsName, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, |
32 | Module, Name, Path, Resolver, Static, Struct, Trait, Ty, | 31 | Module, Name, Path, Resolver, Static, Struct, Ty, |
33 | }; | 32 | }; |
34 | 33 | ||
35 | /// Locates the module by `FileId`. Picks topmost module in the file. | ||
36 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> { | ||
37 | module_from_source(db, file_id.into(), None) | ||
38 | } | ||
39 | |||
40 | /// Locates the child module by `mod child;` declaration. | ||
41 | pub fn module_from_declaration( | ||
42 | db: &impl HirDatabase, | ||
43 | file_id: FileId, | ||
44 | decl: ast::Module, | ||
45 | ) -> Option<Module> { | ||
46 | let parent_module = module_from_file_id(db, file_id); | ||
47 | let child_name = decl.name(); | ||
48 | match (parent_module, child_name) { | ||
49 | (Some(parent_module), Some(child_name)) => parent_module.child(db, &child_name.as_name()), | ||
50 | _ => None, | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /// Locates the module by position in the source code. | ||
55 | pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> { | ||
56 | let parse = db.parse(position.file_id); | ||
57 | match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) { | ||
58 | Some(m) if !m.has_semi() => module_from_inline(db, position.file_id, m.clone()), | ||
59 | _ => module_from_file_id(db, position.file_id), | ||
60 | } | ||
61 | } | ||
62 | |||
63 | fn module_from_inline( | ||
64 | db: &impl HirDatabase, | ||
65 | file_id: FileId, | ||
66 | module: ast::Module, | ||
67 | ) -> Option<Module> { | ||
68 | assert!(!module.has_semi()); | ||
69 | let file_id = file_id.into(); | ||
70 | let ast_id_map = db.ast_id_map(file_id); | ||
71 | let item_id = ast_id_map.ast_id(&module).with_file_id(file_id); | ||
72 | module_from_source(db, file_id, Some(item_id)) | ||
73 | } | ||
74 | |||
75 | /// Locates the module by child syntax element within the module | ||
76 | pub fn module_from_child_node( | ||
77 | db: &impl HirDatabase, | ||
78 | file_id: FileId, | ||
79 | child: &SyntaxNode, | ||
80 | ) -> Option<Module> { | ||
81 | if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { | ||
82 | module_from_inline(db, file_id, m) | ||
83 | } else { | ||
84 | module_from_file_id(db, file_id) | ||
85 | } | ||
86 | } | ||
87 | |||
88 | fn module_from_source( | ||
89 | db: &impl HirDatabase, | ||
90 | file_id: HirFileId, | ||
91 | decl_id: Option<AstId<ast::Module>>, | ||
92 | ) -> Option<Module> { | ||
93 | let source_root_id = db.file_source_root(file_id.as_original_file()); | ||
94 | db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( | ||
95 | |krate| { | ||
96 | let def_map = db.crate_def_map(krate); | ||
97 | let module_id = def_map.find_module_by_source(file_id, decl_id)?; | ||
98 | Some(Module { krate, module_id }) | ||
99 | }, | ||
100 | ) | ||
101 | } | ||
102 | |||
103 | pub fn struct_from_module( | ||
104 | db: &impl HirDatabase, | ||
105 | module: Module, | ||
106 | struct_def: &ast::StructDef, | ||
107 | ) -> Struct { | ||
108 | let file_id = module.definition_source(db).file_id; | ||
109 | let ctx = LocationCtx::new(db, module, file_id); | ||
110 | Struct { id: ctx.to_def(struct_def) } | ||
111 | } | ||
112 | |||
113 | pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { | ||
114 | let file_id = module.definition_source(db).file_id; | ||
115 | let ctx = LocationCtx::new(db, module, file_id); | ||
116 | Enum { id: ctx.to_def(enum_def) } | ||
117 | } | ||
118 | |||
119 | pub fn trait_from_module( | ||
120 | db: &impl HirDatabase, | ||
121 | module: Module, | ||
122 | trait_def: &ast::TraitDef, | ||
123 | ) -> Trait { | ||
124 | let file_id = module.definition_source(db).file_id; | ||
125 | let ctx = LocationCtx::new(db, module, file_id); | ||
126 | Trait { id: ctx.to_def(trait_def) } | ||
127 | } | ||
128 | |||
129 | fn try_get_resolver_for_node( | 34 | fn try_get_resolver_for_node( |
130 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
131 | file_id: FileId, | 36 | file_id: FileId, |
132 | node: &SyntaxNode, | 37 | node: &SyntaxNode, |
133 | ) -> Option<Resolver> { | 38 | ) -> Option<Resolver> { |
134 | if let Some(module) = ast::Module::cast(node.clone()) { | 39 | if let Some(module) = ast::Module::cast(node.clone()) { |
135 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) | 40 | let src = crate::Source { file_id: file_id.into(), ast: module }; |
136 | } else if let Some(_) = ast::SourceFile::cast(node.clone()) { | 41 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) |
137 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) | 42 | } else if let Some(file) = ast::SourceFile::cast(node.clone()) { |
43 | let src = | ||
44 | crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(file) }; | ||
45 | Some(crate::Module::from_definition(db, src)?.resolver(db)) | ||
138 | } else if let Some(s) = ast::StructDef::cast(node.clone()) { | 46 | } else if let Some(s) = ast::StructDef::cast(node.clone()) { |
139 | let module = module_from_child_node(db, file_id, s.syntax())?; | 47 | let src = crate::Source { file_id: file_id.into(), ast: s }; |
140 | Some(struct_from_module(db, module, &s).resolver(db)) | 48 | Some(Struct::from_source(db, src)?.resolver(db)) |
141 | } else if let Some(e) = ast::EnumDef::cast(node.clone()) { | 49 | } else if let Some(e) = ast::EnumDef::cast(node.clone()) { |
142 | let module = module_from_child_node(db, file_id, e.syntax())?; | 50 | let src = crate::Source { file_id: file_id.into(), ast: e }; |
143 | Some(enum_from_module(db, module, &e).resolver(db)) | 51 | Some(Enum::from_source(db, src)?.resolver(db)) |
144 | } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { | 52 | } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { |
145 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) | 53 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) |
146 | } else { | 54 | } else { |
@@ -154,8 +62,10 @@ fn def_with_body_from_child_node( | |||
154 | file_id: FileId, | 62 | file_id: FileId, |
155 | node: &SyntaxNode, | 63 | node: &SyntaxNode, |
156 | ) -> Option<DefWithBody> { | 64 | ) -> Option<DefWithBody> { |
157 | let module = module_from_child_node(db, file_id, node)?; | 65 | let src = crate::ModuleSource::from_child_node(db, file_id, node); |
66 | let module = Module::from_definition(db, crate::Source { file_id: file_id.into(), ast: src })?; | ||
158 | let ctx = LocationCtx::new(db, module, file_id.into()); | 67 | let ctx = LocationCtx::new(db, module, file_id.into()); |
68 | |||
159 | node.ancestors().find_map(|node| { | 69 | node.ancestors().find_map(|node| { |
160 | if let Some(def) = ast::FnDef::cast(node.clone()) { | 70 | if let Some(def) = ast::FnDef::cast(node.clone()) { |
161 | return Some(Function { id: ctx.to_def(&def) }.into()); | 71 | return Some(Function { id: ctx.to_def(&def) }.into()); |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 7139947b3..59bd3689b 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -1,4 +1,3 @@ | |||
1 | use hir::source_binder; | ||
2 | use ra_syntax::{ | 1 | use ra_syntax::{ |
3 | algo::{find_covering_element, find_node_at_offset}, | 2 | algo::{find_covering_element, find_node_at_offset}, |
4 | ast, AstNode, Parse, SourceFile, | 3 | ast, AstNode, Parse, SourceFile, |
@@ -47,7 +46,11 @@ impl<'a> CompletionContext<'a> { | |||
47 | original_parse: &'a Parse<ast::SourceFile>, | 46 | original_parse: &'a Parse<ast::SourceFile>, |
48 | position: FilePosition, | 47 | position: FilePosition, |
49 | ) -> Option<CompletionContext<'a>> { | 48 | ) -> Option<CompletionContext<'a>> { |
50 | let module = source_binder::module_from_position(db, position); | 49 | let src = hir::ModuleSource::from_position(db, position); |
50 | let module = hir::Module::from_definition( | ||
51 | db, | ||
52 | hir::Source { file_id: position.file_id.into(), ast: src }, | ||
53 | ); | ||
51 | let token = | 54 | let token = |
52 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; | 55 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; |
53 | let analyzer = | 56 | let analyzer = |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index c448aa8c5..1ae152e5b 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -1,9 +1,6 @@ | |||
1 | use std::cell::RefCell; | 1 | use std::cell::RefCell; |
2 | 2 | ||
3 | use hir::{ | 3 | use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}; |
4 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}, | ||
5 | source_binder, | ||
6 | }; | ||
7 | use itertools::Itertools; | 4 | use itertools::Itertools; |
8 | use ra_assists::ast_editor::{AstBuilder, AstEditor}; | 5 | use ra_assists::ast_editor::{AstBuilder, AstEditor}; |
9 | use ra_db::SourceDatabase; | 6 | use ra_db::SourceDatabase; |
@@ -89,7 +86,10 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
89 | fix: Some(fix), | 86 | fix: Some(fix), |
90 | }) | 87 | }) |
91 | }); | 88 | }); |
92 | if let Some(m) = source_binder::module_from_file_id(db, file_id) { | 89 | let source_file = db.parse(file_id).tree().to_owned(); |
90 | let src = | ||
91 | hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) }; | ||
92 | if let Some(m) = hir::Module::from_definition(db, src) { | ||
93 | m.diagnostics(db, &mut sink); | 93 | m.diagnostics(db, &mut sink); |
94 | }; | 94 | }; |
95 | drop(sink); | 95 | drop(sink); |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 503dcacff..bc8863dad 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -96,9 +96,8 @@ pub(crate) fn name_definition( | |||
96 | 96 | ||
97 | if let Some(module) = ast::Module::cast(parent.clone()) { | 97 | if let Some(module) = ast::Module::cast(parent.clone()) { |
98 | if module.has_semi() { | 98 | if module.has_semi() { |
99 | if let Some(child_module) = | 99 | let src = hir::Source { file_id: file_id.into(), ast: module }; |
100 | hir::source_binder::module_from_declaration(db, file_id, module) | 100 | if let Some(child_module) = hir::Module::from_declaration(db, src) { |
101 | { | ||
102 | let nav = NavigationTarget::from_module(db, child_module); | 101 | let nav = NavigationTarget::from_module(db, child_module); |
103 | return Some(vec![nav]); | 102 | return Some(vec![nav]); |
104 | } | 103 | } |
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index c5620dd52..f57f9a21b 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{db::HirDatabase, source_binder, ApplicationTy, Ty, TypeCtor}; | 1 | use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor}; |
2 | use ra_db::SourceDatabase; | 2 | use ra_db::SourceDatabase; |
3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; |
4 | 4 | ||
@@ -11,17 +11,21 @@ pub(crate) fn goto_implementation( | |||
11 | let parse = db.parse(position.file_id); | 11 | let parse = db.parse(position.file_id); |
12 | let syntax = parse.tree().syntax().clone(); | 12 | let syntax = parse.tree().syntax().clone(); |
13 | 13 | ||
14 | let module = source_binder::module_from_position(db, position)?; | 14 | let src = hir::ModuleSource::from_position(db, position); |
15 | let module = hir::Module::from_definition( | ||
16 | db, | ||
17 | hir::Source { file_id: position.file_id.into(), ast: src }, | ||
18 | )?; | ||
15 | 19 | ||
16 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { | 20 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { |
17 | return Some(RangeInfo::new( | 21 | return Some(RangeInfo::new( |
18 | nominal_def.syntax().text_range(), | 22 | nominal_def.syntax().text_range(), |
19 | impls_for_def(db, &nominal_def, module)?, | 23 | impls_for_def(db, position, &nominal_def, module)?, |
20 | )); | 24 | )); |
21 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { | 25 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { |
22 | return Some(RangeInfo::new( | 26 | return Some(RangeInfo::new( |
23 | trait_def.syntax().text_range(), | 27 | trait_def.syntax().text_range(), |
24 | impls_for_trait(db, &trait_def, module)?, | 28 | impls_for_trait(db, position, &trait_def, module)?, |
25 | )); | 29 | )); |
26 | } | 30 | } |
27 | 31 | ||
@@ -30,14 +34,19 @@ pub(crate) fn goto_implementation( | |||
30 | 34 | ||
31 | fn impls_for_def( | 35 | fn impls_for_def( |
32 | db: &RootDatabase, | 36 | db: &RootDatabase, |
37 | position: FilePosition, | ||
33 | node: &ast::NominalDef, | 38 | node: &ast::NominalDef, |
34 | module: hir::Module, | 39 | module: hir::Module, |
35 | ) -> Option<Vec<NavigationTarget>> { | 40 | ) -> Option<Vec<NavigationTarget>> { |
36 | let ty = match node { | 41 | let ty = match node { |
37 | ast::NominalDef::StructDef(def) => { | 42 | ast::NominalDef::StructDef(def) => { |
38 | source_binder::struct_from_module(db, module, &def).ty(db) | 43 | let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; |
44 | hir::Struct::from_source(db, src)?.ty(db) | ||
45 | } | ||
46 | ast::NominalDef::EnumDef(def) => { | ||
47 | let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; | ||
48 | hir::Enum::from_source(db, src)?.ty(db) | ||
39 | } | 49 | } |
40 | ast::NominalDef::EnumDef(def) => source_binder::enum_from_module(db, module, &def).ty(db), | ||
41 | }; | 50 | }; |
42 | 51 | ||
43 | let krate = module.krate(db)?; | 52 | let krate = module.krate(db)?; |
@@ -54,10 +63,12 @@ fn impls_for_def( | |||
54 | 63 | ||
55 | fn impls_for_trait( | 64 | fn impls_for_trait( |
56 | db: &RootDatabase, | 65 | db: &RootDatabase, |
66 | position: FilePosition, | ||
57 | node: &ast::TraitDef, | 67 | node: &ast::TraitDef, |
58 | module: hir::Module, | 68 | module: hir::Module, |
59 | ) -> Option<Vec<NavigationTarget>> { | 69 | ) -> Option<Vec<NavigationTarget>> { |
60 | let tr = source_binder::trait_from_module(db, module, node); | 70 | let src = hir::Source { file_id: position.file_id.into(), ast: node.clone() }; |
71 | let tr = hir::Trait::from_source(db, src)?; | ||
61 | 72 | ||
62 | let krate = module.krate(db)?; | 73 | let krate = module.krate(db)?; |
63 | let impls = db.impls_in_crate(krate); | 74 | let impls = db.impls_in_crate(krate); |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index e90fbd428..412dc4d71 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -223,6 +223,7 @@ impl Query { | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | /// Info associated with a text range. | ||
226 | #[derive(Debug)] | 227 | #[derive(Debug)] |
227 | pub struct RangeInfo<T> { | 228 | pub struct RangeInfo<T> { |
228 | pub range: TextRange, | 229 | pub range: TextRange, |
@@ -235,6 +236,8 @@ impl<T> RangeInfo<T> { | |||
235 | } | 236 | } |
236 | } | 237 | } |
237 | 238 | ||
239 | /// Contains information about a call site. Specifically the | ||
240 | /// `FunctionSignature`and current parameter. | ||
238 | #[derive(Debug)] | 241 | #[derive(Debug)] |
239 | pub struct CallInfo { | 242 | pub struct CallInfo { |
240 | pub signature: FunctionSignature, | 243 | pub signature: FunctionSignature, |
@@ -325,11 +328,12 @@ impl Analysis { | |||
325 | (host.analysis(), file_id) | 328 | (host.analysis(), file_id) |
326 | } | 329 | } |
327 | 330 | ||
331 | /// Features for Analysis. | ||
328 | pub fn feature_flags(&self) -> &FeatureFlags { | 332 | pub fn feature_flags(&self) -> &FeatureFlags { |
329 | &self.db.feature_flags | 333 | &self.db.feature_flags |
330 | } | 334 | } |
331 | 335 | ||
332 | /// Debug info about the current state of the analysis | 336 | /// Debug info about the current state of the analysis. |
333 | pub fn status(&self) -> Cancelable<String> { | 337 | pub fn status(&self) -> Cancelable<String> { |
334 | self.with_db(|db| status::status(&*db)) | 338 | self.with_db(|db| status::status(&*db)) |
335 | } | 339 | } |
@@ -440,6 +444,7 @@ impl Analysis { | |||
440 | }) | 444 | }) |
441 | } | 445 | } |
442 | 446 | ||
447 | /// Returns the definitions from the symbol at `position`. | ||
443 | pub fn goto_definition( | 448 | pub fn goto_definition( |
444 | &self, | 449 | &self, |
445 | position: FilePosition, | 450 | position: FilePosition, |
@@ -447,6 +452,7 @@ impl Analysis { | |||
447 | self.with_db(|db| goto_definition::goto_definition(db, position)) | 452 | self.with_db(|db| goto_definition::goto_definition(db, position)) |
448 | } | 453 | } |
449 | 454 | ||
455 | /// Returns the impls from the symbol at `position`. | ||
450 | pub fn goto_implementation( | 456 | pub fn goto_implementation( |
451 | &self, | 457 | &self, |
452 | position: FilePosition, | 458 | position: FilePosition, |
@@ -454,6 +460,7 @@ impl Analysis { | |||
454 | self.with_db(|db| impls::goto_implementation(db, position)) | 460 | self.with_db(|db| impls::goto_implementation(db, position)) |
455 | } | 461 | } |
456 | 462 | ||
463 | /// Returns the type definitions for the symbol at `position`. | ||
457 | pub fn goto_type_definition( | 464 | pub fn goto_type_definition( |
458 | &self, | 465 | &self, |
459 | position: FilePosition, | 466 | position: FilePosition, |
@@ -540,6 +547,7 @@ impl Analysis { | |||
540 | self.with_db(|db| references::rename(db, position, new_name)) | 547 | self.with_db(|db| references::rename(db, position, new_name)) |
541 | } | 548 | } |
542 | 549 | ||
550 | /// Performs an operation on that may be Canceled. | ||
543 | fn with_db<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>( | 551 | fn with_db<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>( |
544 | &self, | 552 | &self, |
545 | f: F, | 553 | f: F, |
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs index 7d5f9ea2c..3668da8d7 100644 --- a/crates/ra_ide_api/src/parent_module.rs +++ b/crates/ra_ide_api/src/parent_module.rs | |||
@@ -5,7 +5,11 @@ use crate::{db::RootDatabase, NavigationTarget}; | |||
5 | /// This returns `Vec` because a module may be included from several places. We | 5 | /// This returns `Vec` because a module may be included from several places. We |
6 | /// don't handle this case yet though, so the Vec has length at most one. | 6 | /// don't handle this case yet though, so the Vec has length at most one. |
7 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { | 7 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { |
8 | let module = match hir::source_binder::module_from_position(db, position) { | 8 | let src = hir::ModuleSource::from_position(db, position); |
9 | let module = match hir::Module::from_definition( | ||
10 | db, | ||
11 | hir::Source { file_id: position.file_id.into(), ast: src }, | ||
12 | ) { | ||
9 | None => return Vec::new(), | 13 | None => return Vec::new(), |
10 | Some(it) => it, | 14 | Some(it) => it, |
11 | }; | 15 | }; |
@@ -15,10 +19,12 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na | |||
15 | 19 | ||
16 | /// Returns `Vec` for the same reason as `parent_module` | 20 | /// Returns `Vec` for the same reason as `parent_module` |
17 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { | 21 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { |
18 | let module = match hir::source_binder::module_from_file_id(db, file_id) { | 22 | let src = hir::ModuleSource::from_file_id(db, file_id); |
19 | Some(it) => it, | 23 | let module = |
20 | None => return Vec::new(), | 24 | match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src }) { |
21 | }; | 25 | Some(it) => it, |
26 | None => return Vec::new(), | ||
27 | }; | ||
22 | let krate = match module.krate(db) { | 28 | let krate = match module.krate(db) { |
23 | Some(it) => it, | 29 | Some(it) => it, |
24 | None => return Vec::new(), | 30 | None => return Vec::new(), |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 5f1f0efc3..acca71f2a 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{source_binder, Either, ModuleSource}; | 1 | use hir::{Either, ModuleSource}; |
2 | use ra_db::SourceDatabase; | 2 | use ra_db::SourceDatabase; |
3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode}; | 3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode}; |
4 | use relative_path::{RelativePath, RelativePathBuf}; | 4 | use relative_path::{RelativePath, RelativePathBuf}; |
@@ -135,9 +135,8 @@ fn rename_mod( | |||
135 | ) -> Option<SourceChange> { | 135 | ) -> Option<SourceChange> { |
136 | let mut source_file_edits = Vec::new(); | 136 | let mut source_file_edits = Vec::new(); |
137 | let mut file_system_edits = Vec::new(); | 137 | let mut file_system_edits = Vec::new(); |
138 | if let Some(module) = | 138 | let module_src = hir::Source { file_id: position.file_id.into(), ast: ast_module.clone() }; |
139 | source_binder::module_from_declaration(db, position.file_id, ast_module.clone()) | 139 | if let Some(module) = hir::Module::from_declaration(db, module_src) { |
140 | { | ||
141 | let src = module.definition_source(db); | 140 | let src = module.definition_source(db); |
142 | let file_id = src.file_id.as_original_file(); | 141 | let file_id = src.file_id.as_original_file(); |
143 | match src.ast { | 142 | match src.ast { |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 9d84b3d08..095ca56c4 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -63,7 +63,9 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti | |||
63 | return None; | 63 | return None; |
64 | } | 64 | } |
65 | let range = module.syntax().text_range(); | 65 | let range = module.syntax().text_range(); |
66 | let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?; | 66 | let src = hir::ModuleSource::from_child_node(db, file_id, &module.syntax()); |
67 | let module = | ||
68 | hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src })?; | ||
67 | 69 | ||
68 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); | 70 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); |
69 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) | 71 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 0158f9b8a..e2355aff9 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -212,7 +212,7 @@ fn opt_visibility(p: &mut Parser) -> bool { | |||
212 | // fn foo() { crate::foo(); } | 212 | // fn foo() { crate::foo(); } |
213 | T![crate] if !p.nth_at(1, T![::]) => { | 213 | T![crate] if !p.nth_at(1, T![::]) => { |
214 | let m = p.start(); | 214 | let m = p.start(); |
215 | p.bump_any(); | 215 | p.bump(T![crate]); |
216 | m.complete(p, VISIBILITY); | 216 | m.complete(p, VISIBILITY); |
217 | } | 217 | } |
218 | _ => return false, | 218 | _ => return false, |
@@ -223,7 +223,7 @@ fn opt_visibility(p: &mut Parser) -> bool { | |||
223 | fn opt_alias(p: &mut Parser) { | 223 | fn opt_alias(p: &mut Parser) { |
224 | if p.at(T![as]) { | 224 | if p.at(T![as]) { |
225 | let m = p.start(); | 225 | let m = p.start(); |
226 | p.bump_any(); | 226 | p.bump(T![as]); |
227 | if !p.eat(T![_]) { | 227 | if !p.eat(T![_]) { |
228 | name(p); | 228 | name(p); |
229 | } | 229 | } |
@@ -234,7 +234,7 @@ fn opt_alias(p: &mut Parser) { | |||
234 | fn abi(p: &mut Parser) { | 234 | fn abi(p: &mut Parser) { |
235 | assert!(p.at(T![extern])); | 235 | assert!(p.at(T![extern])); |
236 | let abi = p.start(); | 236 | let abi = p.start(); |
237 | p.bump_any(); | 237 | p.bump(T![extern]); |
238 | match p.current() { | 238 | match p.current() { |
239 | STRING | RAW_STRING => p.bump_any(), | 239 | STRING | RAW_STRING => p.bump_any(), |
240 | _ => (), | 240 | _ => (), |
@@ -257,7 +257,7 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool { | |||
257 | fn name_r(p: &mut Parser, recovery: TokenSet) { | 257 | fn name_r(p: &mut Parser, recovery: TokenSet) { |
258 | if p.at(IDENT) { | 258 | if p.at(IDENT) { |
259 | let m = p.start(); | 259 | let m = p.start(); |
260 | p.bump_any(); | 260 | p.bump(IDENT); |
261 | m.complete(p, NAME); | 261 | m.complete(p, NAME); |
262 | } else { | 262 | } else { |
263 | p.err_recover("expected a name", recovery); | 263 | p.err_recover("expected a name", recovery); |
@@ -271,11 +271,11 @@ fn name(p: &mut Parser) { | |||
271 | fn name_ref(p: &mut Parser) { | 271 | fn name_ref(p: &mut Parser) { |
272 | if p.at(IDENT) { | 272 | if p.at(IDENT) { |
273 | let m = p.start(); | 273 | let m = p.start(); |
274 | p.bump_any(); | 274 | p.bump(IDENT); |
275 | m.complete(p, NAME_REF); | 275 | m.complete(p, NAME_REF); |
276 | } else if p.at(T![self]) { | 276 | } else if p.at(T![self]) { |
277 | let m = p.start(); | 277 | let m = p.start(); |
278 | p.bump_any(); | 278 | p.bump(T![self]); |
279 | m.complete(p, T![self]); | 279 | m.complete(p, T![self]); |
280 | } else { | 280 | } else { |
281 | p.err_and_bump("expected identifier"); | 281 | p.err_and_bump("expected identifier"); |
@@ -296,7 +296,7 @@ fn error_block(p: &mut Parser, message: &str) { | |||
296 | assert!(p.at(T!['{'])); | 296 | assert!(p.at(T!['{'])); |
297 | let m = p.start(); | 297 | let m = p.start(); |
298 | p.error(message); | 298 | p.error(message); |
299 | p.bump_any(); | 299 | p.bump(T!['{']); |
300 | expressions::expr_block_contents(p); | 300 | expressions::expr_block_contents(p); |
301 | p.eat(T!['}']); | 301 | p.eat(T!['}']); |
302 | m.complete(p, ERROR); | 302 | m.complete(p, ERROR); |
diff --git a/crates/ra_parser/src/grammar/attributes.rs b/crates/ra_parser/src/grammar/attributes.rs index 81a363a57..1cfd301b5 100644 --- a/crates/ra_parser/src/grammar/attributes.rs +++ b/crates/ra_parser/src/grammar/attributes.rs | |||
@@ -15,11 +15,11 @@ pub(super) fn outer_attributes(p: &mut Parser) { | |||
15 | fn attribute(p: &mut Parser, inner: bool) { | 15 | fn attribute(p: &mut Parser, inner: bool) { |
16 | let attr = p.start(); | 16 | let attr = p.start(); |
17 | assert!(p.at(T![#])); | 17 | assert!(p.at(T![#])); |
18 | p.bump_any(); | 18 | p.bump(T![#]); |
19 | 19 | ||
20 | if inner { | 20 | if inner { |
21 | assert!(p.at(T![!])); | 21 | assert!(p.at(T![!])); |
22 | p.bump_any(); | 22 | p.bump(T![!]); |
23 | } | 23 | } |
24 | 24 | ||
25 | if p.at(T!['[']) { | 25 | if p.at(T!['[']) { |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 1dd9a586c..80b085280 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -43,7 +43,7 @@ pub(crate) fn block(p: &mut Parser) { | |||
43 | pub(crate) fn naked_block(p: &mut Parser) { | 43 | pub(crate) fn naked_block(p: &mut Parser) { |
44 | assert!(p.at(T!['{'])); | 44 | assert!(p.at(T!['{'])); |
45 | let m = p.start(); | 45 | let m = p.start(); |
46 | p.bump_any(); | 46 | p.bump(T!['{']); |
47 | expr_block_contents(p); | 47 | expr_block_contents(p); |
48 | p.expect(T!['}']); | 48 | p.expect(T!['}']); |
49 | m.complete(p, BLOCK); | 49 | m.complete(p, BLOCK); |
@@ -150,7 +150,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
150 | // } | 150 | // } |
151 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { | 151 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { |
152 | assert!(p.at(T![let])); | 152 | assert!(p.at(T![let])); |
153 | p.bump_any(); | 153 | p.bump(T![let]); |
154 | patterns::pattern(p); | 154 | patterns::pattern(p); |
155 | if p.at(T![:]) { | 155 | if p.at(T![:]) { |
156 | types::ascription(p); | 156 | types::ascription(p); |
@@ -195,7 +195,7 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
195 | // } | 195 | // } |
196 | 196 | ||
197 | if p.at(T![;]) { | 197 | if p.at(T![;]) { |
198 | p.bump_any(); | 198 | p.bump(T![;]); |
199 | continue; | 199 | continue; |
200 | } | 200 | } |
201 | 201 | ||
@@ -297,7 +297,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> | |||
297 | // } | 297 | // } |
298 | T![&] => { | 298 | T![&] => { |
299 | m = p.start(); | 299 | m = p.start(); |
300 | p.bump_any(); | 300 | p.bump(T![&]); |
301 | p.eat(T![mut]); | 301 | p.eat(T![mut]); |
302 | REF_EXPR | 302 | REF_EXPR |
303 | } | 303 | } |
@@ -438,7 +438,7 @@ fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
438 | fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 438 | fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
439 | assert!(p.at(T!['['])); | 439 | assert!(p.at(T!['['])); |
440 | let m = lhs.precede(p); | 440 | let m = lhs.precede(p); |
441 | p.bump_any(); | 441 | p.bump(T!['[']); |
442 | expr(p); | 442 | expr(p); |
443 | p.expect(T![']']); | 443 | p.expect(T![']']); |
444 | m.complete(p, INDEX_EXPR) | 444 | m.complete(p, INDEX_EXPR) |
@@ -478,7 +478,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
478 | fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 478 | fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
479 | assert!(p.at(T![.])); | 479 | assert!(p.at(T![.])); |
480 | let m = lhs.precede(p); | 480 | let m = lhs.precede(p); |
481 | p.bump_any(); | 481 | p.bump(T![.]); |
482 | if p.at(IDENT) || p.at(INT_NUMBER) { | 482 | if p.at(IDENT) || p.at(INT_NUMBER) { |
483 | name_ref_or_index(p) | 483 | name_ref_or_index(p) |
484 | } else if p.at(FLOAT_NUMBER) { | 484 | } else if p.at(FLOAT_NUMBER) { |
@@ -497,7 +497,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
497 | fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 497 | fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
498 | assert!(p.at(T![?])); | 498 | assert!(p.at(T![?])); |
499 | let m = lhs.precede(p); | 499 | let m = lhs.precede(p); |
500 | p.bump_any(); | 500 | p.bump(T![?]); |
501 | m.complete(p, TRY_EXPR) | 501 | m.complete(p, TRY_EXPR) |
502 | } | 502 | } |
503 | 503 | ||
@@ -511,7 +511,7 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
511 | fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | 511 | fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { |
512 | assert!(p.at(T![as])); | 512 | assert!(p.at(T![as])); |
513 | let m = lhs.precede(p); | 513 | let m = lhs.precede(p); |
514 | p.bump_any(); | 514 | p.bump(T![as]); |
515 | // Use type_no_bounds(), because cast expressions are not | 515 | // Use type_no_bounds(), because cast expressions are not |
516 | // allowed to have bounds. | 516 | // allowed to have bounds. |
517 | types::type_no_bounds(p); | 517 | types::type_no_bounds(p); |
@@ -521,7 +521,7 @@ fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { | |||
521 | fn arg_list(p: &mut Parser) { | 521 | fn arg_list(p: &mut Parser) { |
522 | assert!(p.at(T!['('])); | 522 | assert!(p.at(T!['('])); |
523 | let m = p.start(); | 523 | let m = p.start(); |
524 | p.bump_any(); | 524 | p.bump(T!['(']); |
525 | while !p.at(T![')']) && !p.at(EOF) { | 525 | while !p.at(T![')']) && !p.at(EOF) { |
526 | if !p.at_ts(EXPR_FIRST) { | 526 | if !p.at_ts(EXPR_FIRST) { |
527 | p.error("expected expression"); | 527 | p.error("expected expression"); |
@@ -570,7 +570,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { | |||
570 | pub(crate) fn record_field_list(p: &mut Parser) { | 570 | pub(crate) fn record_field_list(p: &mut Parser) { |
571 | assert!(p.at(T!['{'])); | 571 | assert!(p.at(T!['{'])); |
572 | let m = p.start(); | 572 | let m = p.start(); |
573 | p.bump_any(); | 573 | p.bump(T!['{']); |
574 | while !p.at(EOF) && !p.at(T!['}']) { | 574 | while !p.at(EOF) && !p.at(T!['}']) { |
575 | match p.current() { | 575 | match p.current() { |
576 | // test record_literal_field_with_attr | 576 | // test record_literal_field_with_attr |
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 6e295fbf9..6c7fdc2cd 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -101,14 +101,14 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar | |||
101 | } | 101 | } |
102 | T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => { | 102 | T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => { |
103 | let m = p.start(); | 103 | let m = p.start(); |
104 | p.bump_any(); | 104 | p.bump(T![async]); |
105 | p.eat(T![move]); | 105 | p.eat(T![move]); |
106 | block_expr(p, Some(m)) | 106 | block_expr(p, Some(m)) |
107 | } | 107 | } |
108 | T![match] => match_expr(p), | 108 | T![match] => match_expr(p), |
109 | T![unsafe] if la == T!['{'] => { | 109 | T![unsafe] if la == T!['{'] => { |
110 | let m = p.start(); | 110 | let m = p.start(); |
111 | p.bump_any(); | 111 | p.bump(T![unsafe]); |
112 | block_expr(p, Some(m)) | 112 | block_expr(p, Some(m)) |
113 | } | 113 | } |
114 | T!['{'] => { | 114 | T!['{'] => { |
@@ -180,7 +180,7 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker { | |||
180 | fn array_expr(p: &mut Parser) -> CompletedMarker { | 180 | fn array_expr(p: &mut Parser) -> CompletedMarker { |
181 | assert!(p.at(T!['['])); | 181 | assert!(p.at(T!['['])); |
182 | let m = p.start(); | 182 | let m = p.start(); |
183 | p.bump_any(); | 183 | p.bump(T!['[']); |
184 | if p.eat(T![']']) { | 184 | if p.eat(T![']']) { |
185 | return m.complete(p, ARRAY_EXPR); | 185 | return m.complete(p, ARRAY_EXPR); |
186 | } | 186 | } |
@@ -262,11 +262,11 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { | |||
262 | fn if_expr(p: &mut Parser) -> CompletedMarker { | 262 | fn if_expr(p: &mut Parser) -> CompletedMarker { |
263 | assert!(p.at(T![if])); | 263 | assert!(p.at(T![if])); |
264 | let m = p.start(); | 264 | let m = p.start(); |
265 | p.bump_any(); | 265 | p.bump(T![if]); |
266 | cond(p); | 266 | cond(p); |
267 | block(p); | 267 | block(p); |
268 | if p.at(T![else]) { | 268 | if p.at(T![else]) { |
269 | p.bump_any(); | 269 | p.bump(T![else]); |
270 | if p.at(T![if]) { | 270 | if p.at(T![if]) { |
271 | if_expr(p); | 271 | if_expr(p); |
272 | } else { | 272 | } else { |
@@ -285,7 +285,7 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { | |||
285 | fn label(p: &mut Parser) { | 285 | fn label(p: &mut Parser) { |
286 | assert!(p.at(LIFETIME) && p.nth(1) == T![:]); | 286 | assert!(p.at(LIFETIME) && p.nth(1) == T![:]); |
287 | let m = p.start(); | 287 | let m = p.start(); |
288 | p.bump_any(); | 288 | p.bump(LIFETIME); |
289 | p.bump_any(); | 289 | p.bump_any(); |
290 | m.complete(p, LABEL); | 290 | m.complete(p, LABEL); |
291 | } | 291 | } |
@@ -297,7 +297,7 @@ fn label(p: &mut Parser) { | |||
297 | fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | 297 | fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
298 | assert!(p.at(T![loop])); | 298 | assert!(p.at(T![loop])); |
299 | let m = m.unwrap_or_else(|| p.start()); | 299 | let m = m.unwrap_or_else(|| p.start()); |
300 | p.bump_any(); | 300 | p.bump(T![loop]); |
301 | block(p); | 301 | block(p); |
302 | m.complete(p, LOOP_EXPR) | 302 | m.complete(p, LOOP_EXPR) |
303 | } | 303 | } |
@@ -310,7 +310,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | |||
310 | fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | 310 | fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
311 | assert!(p.at(T![while])); | 311 | assert!(p.at(T![while])); |
312 | let m = m.unwrap_or_else(|| p.start()); | 312 | let m = m.unwrap_or_else(|| p.start()); |
313 | p.bump_any(); | 313 | p.bump(T![while]); |
314 | cond(p); | 314 | cond(p); |
315 | block(p); | 315 | block(p); |
316 | m.complete(p, WHILE_EXPR) | 316 | m.complete(p, WHILE_EXPR) |
@@ -323,7 +323,7 @@ fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | |||
323 | fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | 323 | fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
324 | assert!(p.at(T![for])); | 324 | assert!(p.at(T![for])); |
325 | let m = m.unwrap_or_else(|| p.start()); | 325 | let m = m.unwrap_or_else(|| p.start()); |
326 | p.bump_any(); | 326 | p.bump(T![for]); |
327 | patterns::pattern(p); | 327 | patterns::pattern(p); |
328 | p.expect(T![in]); | 328 | p.expect(T![in]); |
329 | expr_no_struct(p); | 329 | expr_no_struct(p); |
@@ -357,7 +357,7 @@ fn cond(p: &mut Parser) { | |||
357 | fn match_expr(p: &mut Parser) -> CompletedMarker { | 357 | fn match_expr(p: &mut Parser) -> CompletedMarker { |
358 | assert!(p.at(T![match])); | 358 | assert!(p.at(T![match])); |
359 | let m = p.start(); | 359 | let m = p.start(); |
360 | p.bump_any(); | 360 | p.bump(T![match]); |
361 | expr_no_struct(p); | 361 | expr_no_struct(p); |
362 | if p.at(T!['{']) { | 362 | if p.at(T!['{']) { |
363 | match_arm_list(p); | 363 | match_arm_list(p); |
@@ -453,7 +453,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { | |||
453 | fn match_guard(p: &mut Parser) -> CompletedMarker { | 453 | fn match_guard(p: &mut Parser) -> CompletedMarker { |
454 | assert!(p.at(T![if])); | 454 | assert!(p.at(T![if])); |
455 | let m = p.start(); | 455 | let m = p.start(); |
456 | p.bump_any(); | 456 | p.bump(T![if]); |
457 | expr(p); | 457 | expr(p); |
458 | m.complete(p, MATCH_GUARD) | 458 | m.complete(p, MATCH_GUARD) |
459 | } | 459 | } |
@@ -479,7 +479,7 @@ pub(super) fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | |||
479 | fn return_expr(p: &mut Parser) -> CompletedMarker { | 479 | fn return_expr(p: &mut Parser) -> CompletedMarker { |
480 | assert!(p.at(T![return])); | 480 | assert!(p.at(T![return])); |
481 | let m = p.start(); | 481 | let m = p.start(); |
482 | p.bump_any(); | 482 | p.bump(T![return]); |
483 | if p.at_ts(EXPR_FIRST) { | 483 | if p.at_ts(EXPR_FIRST) { |
484 | expr(p); | 484 | expr(p); |
485 | } | 485 | } |
@@ -496,7 +496,7 @@ fn return_expr(p: &mut Parser) -> CompletedMarker { | |||
496 | fn continue_expr(p: &mut Parser) -> CompletedMarker { | 496 | fn continue_expr(p: &mut Parser) -> CompletedMarker { |
497 | assert!(p.at(T![continue])); | 497 | assert!(p.at(T![continue])); |
498 | let m = p.start(); | 498 | let m = p.start(); |
499 | p.bump_any(); | 499 | p.bump(T![continue]); |
500 | p.eat(LIFETIME); | 500 | p.eat(LIFETIME); |
501 | m.complete(p, CONTINUE_EXPR) | 501 | m.complete(p, CONTINUE_EXPR) |
502 | } | 502 | } |
@@ -513,7 +513,7 @@ fn continue_expr(p: &mut Parser) -> CompletedMarker { | |||
513 | fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { | 513 | fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { |
514 | assert!(p.at(T![break])); | 514 | assert!(p.at(T![break])); |
515 | let m = p.start(); | 515 | let m = p.start(); |
516 | p.bump_any(); | 516 | p.bump(T![break]); |
517 | p.eat(LIFETIME); | 517 | p.eat(LIFETIME); |
518 | // test break_ambiguity | 518 | // test break_ambiguity |
519 | // fn foo(){ | 519 | // fn foo(){ |
@@ -535,7 +535,7 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { | |||
535 | fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | 535 | fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
536 | assert!(p.at(T![try])); | 536 | assert!(p.at(T![try])); |
537 | let m = m.unwrap_or_else(|| p.start()); | 537 | let m = m.unwrap_or_else(|| p.start()); |
538 | p.bump_any(); | 538 | p.bump(T![try]); |
539 | block(p); | 539 | block(p); |
540 | m.complete(p, TRY_EXPR) | 540 | m.complete(p, TRY_EXPR) |
541 | } | 541 | } |
@@ -549,7 +549,7 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | |||
549 | fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | 549 | fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { |
550 | assert!(p.at(T![box])); | 550 | assert!(p.at(T![box])); |
551 | let m = m.unwrap_or_else(|| p.start()); | 551 | let m = m.unwrap_or_else(|| p.start()); |
552 | p.bump_any(); | 552 | p.bump(T![box]); |
553 | if p.at_ts(EXPR_FIRST) { | 553 | if p.at_ts(EXPR_FIRST) { |
554 | expr(p); | 554 | expr(p); |
555 | } | 555 | } |
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 4dd80d443..4c67a5c2e 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -64,7 +64,7 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF | |||
64 | } else if p.at(T!['}']) && !stop_on_r_curly { | 64 | } else if p.at(T!['}']) && !stop_on_r_curly { |
65 | let e = p.start(); | 65 | let e = p.start(); |
66 | p.error("unmatched `}`"); | 66 | p.error("unmatched `}`"); |
67 | p.bump_any(); | 67 | p.bump(T!['}']); |
68 | e.complete(p, ERROR); | 68 | e.complete(p, ERROR); |
69 | } else if !p.at(EOF) && !p.at(T!['}']) { | 69 | } else if !p.at(EOF) && !p.at(T!['}']) { |
70 | p.err_and_bump("expected an item"); | 70 | p.err_and_bump("expected an item"); |
@@ -276,9 +276,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> { | |||
276 | 276 | ||
277 | fn extern_crate_item(p: &mut Parser, m: Marker) { | 277 | fn extern_crate_item(p: &mut Parser, m: Marker) { |
278 | assert!(p.at(T![extern])); | 278 | assert!(p.at(T![extern])); |
279 | p.bump_any(); | 279 | p.bump(T![extern]); |
280 | assert!(p.at(T![crate])); | 280 | assert!(p.at(T![crate])); |
281 | p.bump_any(); | 281 | p.bump(T![crate]); |
282 | name_ref(p); | 282 | name_ref(p); |
283 | opt_alias(p); | 283 | opt_alias(p); |
284 | p.expect(T![;]); | 284 | p.expect(T![;]); |
@@ -288,7 +288,7 @@ fn extern_crate_item(p: &mut Parser, m: Marker) { | |||
288 | pub(crate) fn extern_item_list(p: &mut Parser) { | 288 | pub(crate) fn extern_item_list(p: &mut Parser) { |
289 | assert!(p.at(T!['{'])); | 289 | assert!(p.at(T!['{'])); |
290 | let m = p.start(); | 290 | let m = p.start(); |
291 | p.bump_any(); | 291 | p.bump(T!['{']); |
292 | mod_contents(p, true); | 292 | mod_contents(p, true); |
293 | p.expect(T!['}']); | 293 | p.expect(T!['}']); |
294 | m.complete(p, EXTERN_ITEM_LIST); | 294 | m.complete(p, EXTERN_ITEM_LIST); |
@@ -296,7 +296,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) { | |||
296 | 296 | ||
297 | fn fn_def(p: &mut Parser, flavor: ItemFlavor) { | 297 | fn fn_def(p: &mut Parser, flavor: ItemFlavor) { |
298 | assert!(p.at(T![fn])); | 298 | assert!(p.at(T![fn])); |
299 | p.bump_any(); | 299 | p.bump(T![fn]); |
300 | 300 | ||
301 | name_r(p, ITEM_RECOVERY_SET); | 301 | name_r(p, ITEM_RECOVERY_SET); |
302 | // test function_type_params | 302 | // test function_type_params |
@@ -323,7 +323,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) { | |||
323 | // test fn_decl | 323 | // test fn_decl |
324 | // trait T { fn foo(); } | 324 | // trait T { fn foo(); } |
325 | if p.at(T![;]) { | 325 | if p.at(T![;]) { |
326 | p.bump_any(); | 326 | p.bump(T![;]); |
327 | } else { | 327 | } else { |
328 | expressions::block(p) | 328 | expressions::block(p) |
329 | } | 329 | } |
@@ -333,7 +333,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) { | |||
333 | // type Foo = Bar; | 333 | // type Foo = Bar; |
334 | fn type_def(p: &mut Parser, m: Marker) { | 334 | fn type_def(p: &mut Parser, m: Marker) { |
335 | assert!(p.at(T![type])); | 335 | assert!(p.at(T![type])); |
336 | p.bump_any(); | 336 | p.bump(T![type]); |
337 | 337 | ||
338 | name(p); | 338 | name(p); |
339 | 339 | ||
@@ -357,7 +357,7 @@ fn type_def(p: &mut Parser, m: Marker) { | |||
357 | 357 | ||
358 | pub(crate) fn mod_item(p: &mut Parser, m: Marker) { | 358 | pub(crate) fn mod_item(p: &mut Parser, m: Marker) { |
359 | assert!(p.at(T![mod])); | 359 | assert!(p.at(T![mod])); |
360 | p.bump_any(); | 360 | p.bump(T![mod]); |
361 | 361 | ||
362 | name(p); | 362 | name(p); |
363 | if p.at(T!['{']) { | 363 | if p.at(T!['{']) { |
@@ -371,7 +371,7 @@ pub(crate) fn mod_item(p: &mut Parser, m: Marker) { | |||
371 | pub(crate) fn mod_item_list(p: &mut Parser) { | 371 | pub(crate) fn mod_item_list(p: &mut Parser) { |
372 | assert!(p.at(T!['{'])); | 372 | assert!(p.at(T!['{'])); |
373 | let m = p.start(); | 373 | let m = p.start(); |
374 | p.bump_any(); | 374 | p.bump(T!['{']); |
375 | mod_contents(p, true); | 375 | mod_contents(p, true); |
376 | p.expect(T!['}']); | 376 | p.expect(T!['}']); |
377 | m.complete(p, ITEM_LIST); | 377 | m.complete(p, ITEM_LIST); |
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs index 63e0e6e0c..310260689 100644 --- a/crates/ra_parser/src/grammar/items/consts.rs +++ b/crates/ra_parser/src/grammar/items/consts.rs | |||
@@ -10,7 +10,7 @@ pub(super) fn const_def(p: &mut Parser, m: Marker) { | |||
10 | 10 | ||
11 | fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) { | 11 | fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) { |
12 | assert!(p.at(kw)); | 12 | assert!(p.at(kw)); |
13 | p.bump_any(); | 13 | p.bump(kw); |
14 | p.eat(T![mut]); // FIXME: validator to forbid const mut | 14 | p.eat(T![mut]); // FIXME: validator to forbid const mut |
15 | 15 | ||
16 | // Allow `_` in place of an identifier in a `const`. | 16 | // Allow `_` in place of an identifier in a `const`. |
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs index 460acd65e..bede3b692 100644 --- a/crates/ra_parser/src/grammar/items/nominal.rs +++ b/crates/ra_parser/src/grammar/items/nominal.rs | |||
@@ -11,7 +11,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { | |||
11 | type_params::opt_where_clause(p); | 11 | type_params::opt_where_clause(p); |
12 | match p.current() { | 12 | match p.current() { |
13 | T![;] => { | 13 | T![;] => { |
14 | p.bump_any(); | 14 | p.bump(T![;]); |
15 | } | 15 | } |
16 | T!['{'] => record_field_def_list(p), | 16 | T!['{'] => record_field_def_list(p), |
17 | _ => { | 17 | _ => { |
@@ -21,7 +21,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { | |||
21 | } | 21 | } |
22 | } | 22 | } |
23 | T![;] if kind == T![struct] => { | 23 | T![;] if kind == T![struct] => { |
24 | p.bump_any(); | 24 | p.bump(T![;]); |
25 | } | 25 | } |
26 | T!['{'] => record_field_def_list(p), | 26 | T!['{'] => record_field_def_list(p), |
27 | T!['('] if kind == T![struct] => { | 27 | T!['('] if kind == T![struct] => { |
@@ -44,7 +44,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { | |||
44 | 44 | ||
45 | pub(super) fn enum_def(p: &mut Parser, m: Marker) { | 45 | pub(super) fn enum_def(p: &mut Parser, m: Marker) { |
46 | assert!(p.at(T![enum])); | 46 | assert!(p.at(T![enum])); |
47 | p.bump_any(); | 47 | p.bump(T![enum]); |
48 | name_r(p, ITEM_RECOVERY_SET); | 48 | name_r(p, ITEM_RECOVERY_SET); |
49 | type_params::opt_type_param_list(p); | 49 | type_params::opt_type_param_list(p); |
50 | type_params::opt_where_clause(p); | 50 | type_params::opt_where_clause(p); |
@@ -59,7 +59,7 @@ pub(super) fn enum_def(p: &mut Parser, m: Marker) { | |||
59 | pub(crate) fn enum_variant_list(p: &mut Parser) { | 59 | pub(crate) fn enum_variant_list(p: &mut Parser) { |
60 | assert!(p.at(T!['{'])); | 60 | assert!(p.at(T!['{'])); |
61 | let m = p.start(); | 61 | let m = p.start(); |
62 | p.bump_any(); | 62 | p.bump(T!['{']); |
63 | while !p.at(EOF) && !p.at(T!['}']) { | 63 | while !p.at(EOF) && !p.at(T!['}']) { |
64 | if p.at(T!['{']) { | 64 | if p.at(T!['{']) { |
65 | error_block(p, "expected enum variant"); | 65 | error_block(p, "expected enum variant"); |
@@ -73,7 +73,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) { | |||
73 | T!['{'] => record_field_def_list(p), | 73 | T!['{'] => record_field_def_list(p), |
74 | T!['('] => tuple_field_def_list(p), | 74 | T!['('] => tuple_field_def_list(p), |
75 | T![=] => { | 75 | T![=] => { |
76 | p.bump_any(); | 76 | p.bump(T![=]); |
77 | expressions::expr(p); | 77 | expressions::expr(p); |
78 | } | 78 | } |
79 | _ => (), | 79 | _ => (), |
@@ -94,7 +94,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) { | |||
94 | pub(crate) fn record_field_def_list(p: &mut Parser) { | 94 | pub(crate) fn record_field_def_list(p: &mut Parser) { |
95 | assert!(p.at(T!['{'])); | 95 | assert!(p.at(T!['{'])); |
96 | let m = p.start(); | 96 | let m = p.start(); |
97 | p.bump_any(); | 97 | p.bump(T!['{']); |
98 | while !p.at(T!['}']) && !p.at(EOF) { | 98 | while !p.at(T!['}']) && !p.at(EOF) { |
99 | if p.at(T!['{']) { | 99 | if p.at(T!['{']) { |
100 | error_block(p, "expected field"); | 100 | error_block(p, "expected field"); |
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs index b49221a4b..3742fd197 100644 --- a/crates/ra_parser/src/grammar/items/traits.rs +++ b/crates/ra_parser/src/grammar/items/traits.rs | |||
@@ -5,7 +5,7 @@ use super::*; | |||
5 | // trait X<U: Debug + Display>: Hash + Clone where U: Copy {} | 5 | // trait X<U: Debug + Display>: Hash + Clone where U: Copy {} |
6 | pub(super) fn trait_def(p: &mut Parser) { | 6 | pub(super) fn trait_def(p: &mut Parser) { |
7 | assert!(p.at(T![trait])); | 7 | assert!(p.at(T![trait])); |
8 | p.bump_any(); | 8 | p.bump(T![trait]); |
9 | name_r(p, ITEM_RECOVERY_SET); | 9 | name_r(p, ITEM_RECOVERY_SET); |
10 | type_params::opt_type_param_list(p); | 10 | type_params::opt_type_param_list(p); |
11 | if p.at(T![:]) { | 11 | if p.at(T![:]) { |
@@ -29,7 +29,7 @@ pub(super) fn trait_def(p: &mut Parser) { | |||
29 | pub(crate) fn trait_item_list(p: &mut Parser) { | 29 | pub(crate) fn trait_item_list(p: &mut Parser) { |
30 | assert!(p.at(T!['{'])); | 30 | assert!(p.at(T!['{'])); |
31 | let m = p.start(); | 31 | let m = p.start(); |
32 | p.bump_any(); | 32 | p.bump(T!['{']); |
33 | while !p.at(EOF) && !p.at(T!['}']) { | 33 | while !p.at(EOF) && !p.at(T!['}']) { |
34 | if p.at(T!['{']) { | 34 | if p.at(T!['{']) { |
35 | error_block(p, "expected an item"); | 35 | error_block(p, "expected an item"); |
@@ -45,7 +45,7 @@ pub(crate) fn trait_item_list(p: &mut Parser) { | |||
45 | // impl Foo {} | 45 | // impl Foo {} |
46 | pub(super) fn impl_block(p: &mut Parser) { | 46 | pub(super) fn impl_block(p: &mut Parser) { |
47 | assert!(p.at(T![impl])); | 47 | assert!(p.at(T![impl])); |
48 | p.bump_any(); | 48 | p.bump(T![impl]); |
49 | if choose_type_params_over_qpath(p) { | 49 | if choose_type_params_over_qpath(p) { |
50 | type_params::opt_type_param_list(p); | 50 | type_params::opt_type_param_list(p); |
51 | } | 51 | } |
@@ -78,7 +78,7 @@ pub(super) fn impl_block(p: &mut Parser) { | |||
78 | pub(crate) fn impl_item_list(p: &mut Parser) { | 78 | pub(crate) fn impl_item_list(p: &mut Parser) { |
79 | assert!(p.at(T!['{'])); | 79 | assert!(p.at(T!['{'])); |
80 | let m = p.start(); | 80 | let m = p.start(); |
81 | p.bump_any(); | 81 | p.bump(T!['{']); |
82 | // test impl_inner_attributes | 82 | // test impl_inner_attributes |
83 | // enum F{} | 83 | // enum F{} |
84 | // impl F { | 84 | // impl F { |
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs index f28f522b8..2af2ad315 100644 --- a/crates/ra_parser/src/grammar/items/use_item.rs +++ b/crates/ra_parser/src/grammar/items/use_item.rs | |||
@@ -2,7 +2,7 @@ use super::*; | |||
2 | 2 | ||
3 | pub(super) fn use_item(p: &mut Parser, m: Marker) { | 3 | pub(super) fn use_item(p: &mut Parser, m: Marker) { |
4 | assert!(p.at(T![use])); | 4 | assert!(p.at(T![use])); |
5 | p.bump_any(); | 5 | p.bump(T![use]); |
6 | use_tree(p); | 6 | use_tree(p); |
7 | p.expect(T![;]); | 7 | p.expect(T![;]); |
8 | m.complete(p, USE_ITEM); | 8 | m.complete(p, USE_ITEM); |
@@ -84,7 +84,7 @@ fn use_tree(p: &mut Parser) { | |||
84 | p.bump(T![::]); | 84 | p.bump(T![::]); |
85 | match p.current() { | 85 | match p.current() { |
86 | T![*] => { | 86 | T![*] => { |
87 | p.bump_any(); | 87 | p.bump(T![*]); |
88 | } | 88 | } |
89 | // test use_tree_list_after_path | 89 | // test use_tree_list_after_path |
90 | // use crate::{Item}; | 90 | // use crate::{Item}; |
@@ -114,7 +114,7 @@ fn use_tree(p: &mut Parser) { | |||
114 | pub(crate) fn use_tree_list(p: &mut Parser) { | 114 | pub(crate) fn use_tree_list(p: &mut Parser) { |
115 | assert!(p.at(T!['{'])); | 115 | assert!(p.at(T!['{'])); |
116 | let m = p.start(); | 116 | let m = p.start(); |
117 | p.bump_any(); | 117 | p.bump(T!['{']); |
118 | while !p.at(EOF) && !p.at(T!['}']) { | 118 | while !p.at(EOF) && !p.at(T!['}']) { |
119 | use_tree(p); | 119 | use_tree(p); |
120 | if !p.at(T!['}']) { | 120 | if !p.at(T!['}']) { |
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index 5893b22fd..efc329243 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs | |||
@@ -39,7 +39,7 @@ fn list_(p: &mut Parser, flavor: Flavor) { | |||
39 | let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) }; | 39 | let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) }; |
40 | assert!(p.at(bra)); | 40 | assert!(p.at(bra)); |
41 | let m = p.start(); | 41 | let m = p.start(); |
42 | p.bump_any(); | 42 | p.bump(bra); |
43 | if flavor.type_required() { | 43 | if flavor.type_required() { |
44 | // test self_param_outer_attr | 44 | // test self_param_outer_attr |
45 | // fn f(#[must_use] self) {} | 45 | // fn f(#[must_use] self) {} |
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 919b0f37d..a4ffd6960 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -106,7 +106,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker { | |||
106 | assert!(is_literal_pat_start(p)); | 106 | assert!(is_literal_pat_start(p)); |
107 | let m = p.start(); | 107 | let m = p.start(); |
108 | if p.at(T![-]) { | 108 | if p.at(T![-]) { |
109 | p.bump_any(); | 109 | p.bump(T![-]); |
110 | } | 110 | } |
111 | expressions::literal(p); | 111 | expressions::literal(p); |
112 | m.complete(p, LITERAL_PAT) | 112 | m.complete(p, LITERAL_PAT) |
@@ -146,7 +146,7 @@ fn path_pat(p: &mut Parser) -> CompletedMarker { | |||
146 | // } | 146 | // } |
147 | fn tuple_pat_fields(p: &mut Parser) { | 147 | fn tuple_pat_fields(p: &mut Parser) { |
148 | assert!(p.at(T!['('])); | 148 | assert!(p.at(T!['('])); |
149 | p.bump_any(); | 149 | p.bump(T!['(']); |
150 | pat_list(p, T![')']); | 150 | pat_list(p, T![')']); |
151 | p.expect(T![')']); | 151 | p.expect(T![')']); |
152 | } | 152 | } |
@@ -161,7 +161,7 @@ fn tuple_pat_fields(p: &mut Parser) { | |||
161 | fn record_field_pat_list(p: &mut Parser) { | 161 | fn record_field_pat_list(p: &mut Parser) { |
162 | assert!(p.at(T!['{'])); | 162 | assert!(p.at(T!['{'])); |
163 | let m = p.start(); | 163 | let m = p.start(); |
164 | p.bump_any(); | 164 | p.bump(T!['{']); |
165 | while !p.at(EOF) && !p.at(T!['}']) { | 165 | while !p.at(EOF) && !p.at(T!['}']) { |
166 | match p.current() { | 166 | match p.current() { |
167 | // A trailing `..` is *not* treated as a DOT_DOT_PAT. | 167 | // A trailing `..` is *not* treated as a DOT_DOT_PAT. |
@@ -200,7 +200,7 @@ fn record_field_pat(p: &mut Parser) { | |||
200 | fn placeholder_pat(p: &mut Parser) -> CompletedMarker { | 200 | fn placeholder_pat(p: &mut Parser) -> CompletedMarker { |
201 | assert!(p.at(T![_])); | 201 | assert!(p.at(T![_])); |
202 | let m = p.start(); | 202 | let m = p.start(); |
203 | p.bump_any(); | 203 | p.bump(T![_]); |
204 | m.complete(p, PLACEHOLDER_PAT) | 204 | m.complete(p, PLACEHOLDER_PAT) |
205 | } | 205 | } |
206 | 206 | ||
@@ -245,7 +245,7 @@ fn dot_dot_pat(p: &mut Parser) -> CompletedMarker { | |||
245 | fn ref_pat(p: &mut Parser) -> CompletedMarker { | 245 | fn ref_pat(p: &mut Parser) -> CompletedMarker { |
246 | assert!(p.at(T![&])); | 246 | assert!(p.at(T![&])); |
247 | let m = p.start(); | 247 | let m = p.start(); |
248 | p.bump_any(); | 248 | p.bump(T![&]); |
249 | p.eat(T![mut]); | 249 | p.eat(T![mut]); |
250 | pattern(p); | 250 | pattern(p); |
251 | m.complete(p, REF_PAT) | 251 | m.complete(p, REF_PAT) |
@@ -269,7 +269,7 @@ fn tuple_pat(p: &mut Parser) -> CompletedMarker { | |||
269 | fn slice_pat(p: &mut Parser) -> CompletedMarker { | 269 | fn slice_pat(p: &mut Parser) -> CompletedMarker { |
270 | assert!(p.at(T!['['])); | 270 | assert!(p.at(T!['['])); |
271 | let m = p.start(); | 271 | let m = p.start(); |
272 | p.bump_any(); | 272 | p.bump(T!['[']); |
273 | pat_list(p, T![']']); | 273 | pat_list(p, T![']']); |
274 | p.expect(T![']']); | 274 | p.expect(T![']']); |
275 | m.complete(p, SLICE_PAT) | 275 | m.complete(p, SLICE_PAT) |
@@ -318,7 +318,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { | |||
318 | fn box_pat(p: &mut Parser) -> CompletedMarker { | 318 | fn box_pat(p: &mut Parser) -> CompletedMarker { |
319 | assert!(p.at(T![box])); | 319 | assert!(p.at(T![box])); |
320 | let m = p.start(); | 320 | let m = p.start(); |
321 | p.bump_any(); | 321 | p.bump(T![box]); |
322 | pattern(p); | 322 | pattern(p); |
323 | m.complete(p, BOX_PAT) | 323 | m.complete(p, BOX_PAT) |
324 | } | 324 | } |
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs index edc7d4ff2..8e97fe03c 100644 --- a/crates/ra_parser/src/grammar/type_args.rs +++ b/crates/ra_parser/src/grammar/type_args.rs | |||
@@ -29,7 +29,7 @@ fn type_arg(p: &mut Parser) { | |||
29 | let m = p.start(); | 29 | let m = p.start(); |
30 | match p.current() { | 30 | match p.current() { |
31 | LIFETIME => { | 31 | LIFETIME => { |
32 | p.bump_any(); | 32 | p.bump(LIFETIME); |
33 | m.complete(p, LIFETIME_ARG); | 33 | m.complete(p, LIFETIME_ARG); |
34 | } | 34 | } |
35 | // test associated_type_bounds | 35 | // test associated_type_bounds |
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index 31d709d81..7071c70ea 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs | |||
@@ -10,7 +10,7 @@ pub(super) fn opt_type_param_list(p: &mut Parser) { | |||
10 | fn type_param_list(p: &mut Parser) { | 10 | fn type_param_list(p: &mut Parser) { |
11 | assert!(p.at(T![<])); | 11 | assert!(p.at(T![<])); |
12 | let m = p.start(); | 12 | let m = p.start(); |
13 | p.bump_any(); | 13 | p.bump(T![<]); |
14 | 14 | ||
15 | while !p.at(EOF) && !p.at(T![>]) { | 15 | while !p.at(EOF) && !p.at(T![>]) { |
16 | let m = p.start(); | 16 | let m = p.start(); |
@@ -38,7 +38,7 @@ fn type_param_list(p: &mut Parser) { | |||
38 | 38 | ||
39 | fn lifetime_param(p: &mut Parser, m: Marker) { | 39 | fn lifetime_param(p: &mut Parser, m: Marker) { |
40 | assert!(p.at(LIFETIME)); | 40 | assert!(p.at(LIFETIME)); |
41 | p.bump_any(); | 41 | p.bump(LIFETIME); |
42 | if p.at(T![:]) { | 42 | if p.at(T![:]) { |
43 | lifetime_bounds(p); | 43 | lifetime_bounds(p); |
44 | } | 44 | } |
@@ -54,7 +54,7 @@ fn type_param(p: &mut Parser, m: Marker) { | |||
54 | // test type_param_default | 54 | // test type_param_default |
55 | // struct S<T = i32>; | 55 | // struct S<T = i32>; |
56 | if p.at(T![=]) { | 56 | if p.at(T![=]) { |
57 | p.bump_any(); | 57 | p.bump(T![=]); |
58 | types::type_(p) | 58 | types::type_(p) |
59 | } | 59 | } |
60 | m.complete(p, TYPE_PARAM); | 60 | m.complete(p, TYPE_PARAM); |
@@ -64,15 +64,15 @@ fn type_param(p: &mut Parser, m: Marker) { | |||
64 | // struct S<T: 'a + ?Sized + (Copy)>; | 64 | // struct S<T: 'a + ?Sized + (Copy)>; |
65 | pub(super) fn bounds(p: &mut Parser) { | 65 | pub(super) fn bounds(p: &mut Parser) { |
66 | assert!(p.at(T![:])); | 66 | assert!(p.at(T![:])); |
67 | p.bump_any(); | 67 | p.bump(T![:]); |
68 | bounds_without_colon(p); | 68 | bounds_without_colon(p); |
69 | } | 69 | } |
70 | 70 | ||
71 | fn lifetime_bounds(p: &mut Parser) { | 71 | fn lifetime_bounds(p: &mut Parser) { |
72 | assert!(p.at(T![:])); | 72 | assert!(p.at(T![:])); |
73 | p.bump_any(); | 73 | p.bump(T![:]); |
74 | while p.at(LIFETIME) { | 74 | while p.at(LIFETIME) { |
75 | p.bump_any(); | 75 | p.bump(LIFETIME); |
76 | if !p.eat(T![+]) { | 76 | if !p.eat(T![+]) { |
77 | break; | 77 | break; |
78 | } | 78 | } |
@@ -99,7 +99,7 @@ fn type_bound(p: &mut Parser) -> bool { | |||
99 | let has_paren = p.eat(T!['(']); | 99 | let has_paren = p.eat(T!['(']); |
100 | p.eat(T![?]); | 100 | p.eat(T![?]); |
101 | match p.current() { | 101 | match p.current() { |
102 | LIFETIME => p.bump_any(), | 102 | LIFETIME => p.bump(LIFETIME), |
103 | T![for] => types::for_type(p), | 103 | T![for] => types::for_type(p), |
104 | _ if paths::is_use_path_start(p) => types::path_type_(p, false), | 104 | _ if paths::is_use_path_start(p) => types::path_type_(p, false), |
105 | _ => { | 105 | _ => { |
@@ -128,7 +128,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) { | |||
128 | return; | 128 | return; |
129 | } | 129 | } |
130 | let m = p.start(); | 130 | let m = p.start(); |
131 | p.bump_any(); | 131 | p.bump(T![where]); |
132 | 132 | ||
133 | while is_where_predicate(p) { | 133 | while is_where_predicate(p) { |
134 | where_predicate(p); | 134 | where_predicate(p); |
@@ -166,7 +166,7 @@ fn where_predicate(p: &mut Parser) { | |||
166 | let m = p.start(); | 166 | let m = p.start(); |
167 | match p.current() { | 167 | match p.current() { |
168 | LIFETIME => { | 168 | LIFETIME => { |
169 | p.bump_any(); | 169 | p.bump(LIFETIME); |
170 | if p.at(T![:]) { | 170 | if p.at(T![:]) { |
171 | bounds(p); | 171 | bounds(p); |
172 | } else { | 172 | } else { |
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index a5a5b6d73..4e3522d48 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs | |||
@@ -44,7 +44,7 @@ pub(super) fn ascription(p: &mut Parser) { | |||
44 | fn paren_or_tuple_type(p: &mut Parser) { | 44 | fn paren_or_tuple_type(p: &mut Parser) { |
45 | assert!(p.at(T!['('])); | 45 | assert!(p.at(T!['('])); |
46 | let m = p.start(); | 46 | let m = p.start(); |
47 | p.bump_any(); | 47 | p.bump(T!['(']); |
48 | let mut n_types: u32 = 0; | 48 | let mut n_types: u32 = 0; |
49 | let mut trailing_comma: bool = false; | 49 | let mut trailing_comma: bool = false; |
50 | while !p.at(EOF) && !p.at(T![')']) { | 50 | while !p.at(EOF) && !p.at(T![')']) { |
@@ -79,14 +79,14 @@ fn paren_or_tuple_type(p: &mut Parser) { | |||
79 | fn never_type(p: &mut Parser) { | 79 | fn never_type(p: &mut Parser) { |
80 | assert!(p.at(T![!])); | 80 | assert!(p.at(T![!])); |
81 | let m = p.start(); | 81 | let m = p.start(); |
82 | p.bump_any(); | 82 | p.bump(T![!]); |
83 | m.complete(p, NEVER_TYPE); | 83 | m.complete(p, NEVER_TYPE); |
84 | } | 84 | } |
85 | 85 | ||
86 | fn pointer_type(p: &mut Parser) { | 86 | fn pointer_type(p: &mut Parser) { |
87 | assert!(p.at(T![*])); | 87 | assert!(p.at(T![*])); |
88 | let m = p.start(); | 88 | let m = p.start(); |
89 | p.bump_any(); | 89 | p.bump(T![*]); |
90 | 90 | ||
91 | match p.current() { | 91 | match p.current() { |
92 | // test pointer_type_mut | 92 | // test pointer_type_mut |
@@ -110,21 +110,21 @@ fn pointer_type(p: &mut Parser) { | |||
110 | fn array_or_slice_type(p: &mut Parser) { | 110 | fn array_or_slice_type(p: &mut Parser) { |
111 | assert!(p.at(T!['['])); | 111 | assert!(p.at(T!['['])); |
112 | let m = p.start(); | 112 | let m = p.start(); |
113 | p.bump_any(); | 113 | p.bump(T!['[']); |
114 | 114 | ||
115 | type_(p); | 115 | type_(p); |
116 | let kind = match p.current() { | 116 | let kind = match p.current() { |
117 | // test slice_type | 117 | // test slice_type |
118 | // type T = [()]; | 118 | // type T = [()]; |
119 | T![']'] => { | 119 | T![']'] => { |
120 | p.bump_any(); | 120 | p.bump(T![']']); |
121 | SLICE_TYPE | 121 | SLICE_TYPE |
122 | } | 122 | } |
123 | 123 | ||
124 | // test array_type | 124 | // test array_type |
125 | // type T = [(); 92]; | 125 | // type T = [(); 92]; |
126 | T![;] => { | 126 | T![;] => { |
127 | p.bump_any(); | 127 | p.bump(T![;]); |
128 | expressions::expr(p); | 128 | expressions::expr(p); |
129 | p.expect(T![']']); | 129 | p.expect(T![']']); |
130 | ARRAY_TYPE | 130 | ARRAY_TYPE |
@@ -146,7 +146,7 @@ fn array_or_slice_type(p: &mut Parser) { | |||
146 | fn reference_type(p: &mut Parser) { | 146 | fn reference_type(p: &mut Parser) { |
147 | assert!(p.at(T![&])); | 147 | assert!(p.at(T![&])); |
148 | let m = p.start(); | 148 | let m = p.start(); |
149 | p.bump_any(); | 149 | p.bump(T![&]); |
150 | p.eat(LIFETIME); | 150 | p.eat(LIFETIME); |
151 | p.eat(T![mut]); | 151 | p.eat(T![mut]); |
152 | type_no_bounds(p); | 152 | type_no_bounds(p); |
@@ -158,7 +158,7 @@ fn reference_type(p: &mut Parser) { | |||
158 | fn placeholder_type(p: &mut Parser) { | 158 | fn placeholder_type(p: &mut Parser) { |
159 | assert!(p.at(T![_])); | 159 | assert!(p.at(T![_])); |
160 | let m = p.start(); | 160 | let m = p.start(); |
161 | p.bump_any(); | 161 | p.bump(T![_]); |
162 | m.complete(p, PLACEHOLDER_TYPE); | 162 | m.complete(p, PLACEHOLDER_TYPE); |
163 | } | 163 | } |
164 | 164 | ||
@@ -193,7 +193,7 @@ fn fn_pointer_type(p: &mut Parser) { | |||
193 | 193 | ||
194 | pub(super) fn for_binder(p: &mut Parser) { | 194 | pub(super) fn for_binder(p: &mut Parser) { |
195 | assert!(p.at(T![for])); | 195 | assert!(p.at(T![for])); |
196 | p.bump_any(); | 196 | p.bump(T![for]); |
197 | if p.at(T![<]) { | 197 | if p.at(T![<]) { |
198 | type_params::opt_type_param_list(p); | 198 | type_params::opt_type_param_list(p); |
199 | } else { | 199 | } else { |
@@ -224,7 +224,7 @@ pub(super) fn for_type(p: &mut Parser) { | |||
224 | fn impl_trait_type(p: &mut Parser) { | 224 | fn impl_trait_type(p: &mut Parser) { |
225 | assert!(p.at(T![impl])); | 225 | assert!(p.at(T![impl])); |
226 | let m = p.start(); | 226 | let m = p.start(); |
227 | p.bump_any(); | 227 | p.bump(T![impl]); |
228 | type_params::bounds_without_colon(p); | 228 | type_params::bounds_without_colon(p); |
229 | m.complete(p, IMPL_TRAIT_TYPE); | 229 | m.complete(p, IMPL_TRAIT_TYPE); |
230 | } | 230 | } |
@@ -234,7 +234,7 @@ fn impl_trait_type(p: &mut Parser) { | |||
234 | fn dyn_trait_type(p: &mut Parser) { | 234 | fn dyn_trait_type(p: &mut Parser) { |
235 | assert!(p.at(T![dyn ])); | 235 | assert!(p.at(T![dyn ])); |
236 | let m = p.start(); | 236 | let m = p.start(); |
237 | p.bump_any(); | 237 | p.bump(T![dyn ]); |
238 | type_params::bounds_without_colon(p); | 238 | type_params::bounds_without_colon(p); |
239 | m.complete(p, DYN_TRAIT_TYPE); | 239 | m.complete(p, DYN_TRAIT_TYPE); |
240 | } | 240 | } |