diff options
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 90 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_scope.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/snapshots/completion_item__extern_prelude.snap | 22 | ||||
-rw-r--r-- | crates/ra_ide_api/src/mock_analysis.rs | 12 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model/sysroot.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 10 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/items.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt | 2 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt | 4 |
14 files changed, 190 insertions, 48 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 92ab0f692..a58bf8f87 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -134,7 +134,7 @@ impl Module { | |||
134 | } | 134 | } |
135 | 135 | ||
136 | /// Returns the crate this module is part of. | 136 | /// Returns the crate this module is part of. |
137 | pub fn krate(&self, _db: &impl HirDatabase) -> Option<Crate> { | 137 | pub fn krate(&self, _db: &impl PersistentHirDatabase) -> Option<Crate> { |
138 | Some(self.krate) | 138 | Some(self.krate) |
139 | } | 139 | } |
140 | 140 | ||
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 04cc693b3..681aa9a67 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -34,6 +34,7 @@ use crate::{ | |||
34 | /// module, the set of visible items. | 34 | /// module, the set of visible items. |
35 | #[derive(Default, Debug, PartialEq, Eq)] | 35 | #[derive(Default, Debug, PartialEq, Eq)] |
36 | pub struct ItemMap { | 36 | pub struct ItemMap { |
37 | pub(crate) extern_prelude: FxHashMap<Name, ModuleDef>, | ||
37 | per_module: ArenaMap<ModuleId, ModuleScope>, | 38 | per_module: ArenaMap<ModuleId, ModuleScope>, |
38 | } | 39 | } |
39 | 40 | ||
@@ -204,6 +205,7 @@ where | |||
204 | } | 205 | } |
205 | 206 | ||
206 | pub(crate) fn resolve(mut self) -> ItemMap { | 207 | pub(crate) fn resolve(mut self) -> ItemMap { |
208 | self.populate_extern_prelude(); | ||
207 | for (&module_id, items) in self.input.iter() { | 209 | for (&module_id, items) in self.input.iter() { |
208 | self.populate_module(module_id, Arc::clone(items)); | 210 | self.populate_module(module_id, Arc::clone(items)); |
209 | } | 211 | } |
@@ -227,29 +229,19 @@ where | |||
227 | self.result | 229 | self.result |
228 | } | 230 | } |
229 | 231 | ||
232 | fn populate_extern_prelude(&mut self) { | ||
233 | for dep in self.krate.dependencies(self.db) { | ||
234 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); | ||
235 | if let Some(module) = dep.krate.root_module(self.db) { | ||
236 | self.result | ||
237 | .extern_prelude | ||
238 | .insert(dep.name.clone(), module.into()); | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
230 | fn populate_module(&mut self, module_id: ModuleId, input: Arc<LoweredModule>) { | 243 | fn populate_module(&mut self, module_id: ModuleId, input: Arc<LoweredModule>) { |
231 | let mut module_items = ModuleScope::default(); | 244 | let mut module_items = ModuleScope::default(); |
232 | |||
233 | // Populate extern crates prelude | ||
234 | { | ||
235 | let root_id = module_id.crate_root(&self.module_tree); | ||
236 | let file_id = root_id.file_id(&self.module_tree); | ||
237 | let crate_graph = self.db.crate_graph(); | ||
238 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) | ||
239 | { | ||
240 | let krate = Crate { crate_id }; | ||
241 | for dep in krate.dependencies(self.db) { | ||
242 | if let Some(module) = dep.krate.root_module(self.db) { | ||
243 | let def = module.into(); | ||
244 | self.add_module_item( | ||
245 | &mut module_items, | ||
246 | dep.name.clone(), | ||
247 | PerNs::types(def), | ||
248 | ); | ||
249 | } | ||
250 | } | ||
251 | }; | ||
252 | } | ||
253 | for (import_id, import_data) in input.imports.iter() { | 245 | for (import_id, import_data) in input.imports.iter() { |
254 | if let Some(last_segment) = import_data.path.segments.iter().last() { | 246 | if let Some(last_segment) = import_data.path.segments.iter().last() { |
255 | if !import_data.is_glob { | 247 | if !import_data.is_glob { |
@@ -327,7 +319,16 @@ where | |||
327 | .alias | 319 | .alias |
328 | .clone() | 320 | .clone() |
329 | .unwrap_or_else(|| last_segment.name.clone()); | 321 | .unwrap_or_else(|| last_segment.name.clone()); |
330 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def,); | 322 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
323 | |||
324 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | ||
325 | if let Some(root_module) = self.krate.root_module(self.db) { | ||
326 | if import.is_extern_crate && module_id == root_module.module_id { | ||
327 | if let Some(def) = def.take_types() { | ||
328 | self.result.extern_prelude.insert(name.clone(), def); | ||
329 | } | ||
330 | } | ||
331 | } | ||
331 | self.update(module_id, |items| { | 332 | self.update(module_id, |items| { |
332 | let res = Resolution { | 333 | let res = Resolution { |
333 | def, | 334 | def, |
@@ -389,24 +390,53 @@ impl ItemMap { | |||
389 | original_module: Module, | 390 | original_module: Module, |
390 | path: &Path, | 391 | path: &Path, |
391 | ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { | 392 | ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { |
392 | let mut curr_per_ns: PerNs<ModuleDef> = PerNs::types(match path.kind { | 393 | let mut segments = path.segments.iter().enumerate(); |
393 | PathKind::Crate => original_module.crate_root(db).into(), | 394 | let mut curr_per_ns: PerNs<ModuleDef> = match path.kind { |
394 | PathKind::Self_ | PathKind::Plain => original_module.into(), | 395 | PathKind::Crate => PerNs::types(original_module.crate_root(db).into()), |
396 | PathKind::Self_ => PerNs::types(original_module.into()), | ||
397 | PathKind::Plain => { | ||
398 | let segment = match segments.next() { | ||
399 | Some((_, segment)) => segment, | ||
400 | None => return (PerNs::none(), ReachedFixedPoint::Yes), | ||
401 | }; | ||
402 | // Resolve in: | ||
403 | // - current module / scope | ||
404 | // - extern prelude | ||
405 | match self[original_module.module_id].items.get(&segment.name) { | ||
406 | Some(res) if !res.def.is_none() => res.def, | ||
407 | _ => { | ||
408 | if let Some(def) = self.extern_prelude.get(&segment.name) { | ||
409 | PerNs::types(*def) | ||
410 | } else { | ||
411 | return (PerNs::none(), ReachedFixedPoint::No); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | } | ||
395 | PathKind::Super => { | 416 | PathKind::Super => { |
396 | if let Some(p) = original_module.parent(db) { | 417 | if let Some(p) = original_module.parent(db) { |
397 | p.into() | 418 | PerNs::types(p.into()) |
398 | } else { | 419 | } else { |
399 | log::debug!("super path in root module"); | 420 | log::debug!("super path in root module"); |
400 | return (PerNs::none(), ReachedFixedPoint::Yes); | 421 | return (PerNs::none(), ReachedFixedPoint::Yes); |
401 | } | 422 | } |
402 | } | 423 | } |
403 | PathKind::Abs => { | 424 | PathKind::Abs => { |
404 | // TODO: absolute use is not supported | 425 | // 2018-style absolute path -- only extern prelude |
405 | return (PerNs::none(), ReachedFixedPoint::Yes); | 426 | let segment = match segments.next() { |
427 | Some((_, segment)) => segment, | ||
428 | None => return (PerNs::none(), ReachedFixedPoint::Yes), | ||
429 | }; | ||
430 | if let Some(def) = self.extern_prelude.get(&segment.name) { | ||
431 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | ||
432 | PerNs::types(*def) | ||
433 | } else { | ||
434 | return (PerNs::none(), ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude | ||
435 | } | ||
406 | } | 436 | } |
407 | }); | 437 | }; |
408 | 438 | ||
409 | for (i, segment) in path.segments.iter().enumerate() { | 439 | for (i, segment) in segments { |
410 | let curr = match curr_per_ns.as_ref().take_types() { | 440 | let curr = match curr_per_ns.as_ref().take_types() { |
411 | Some(r) => r, | 441 | Some(r) => r, |
412 | None => { | 442 | None => { |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index df87f520f..7e6e48ae0 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -8,7 +8,7 @@ use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | |||
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | SourceItemId, Path, ModuleSource, Name, | 11 | SourceItemId, Path, PathKind, ModuleSource, Name, |
12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, | 12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, |
13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, | 13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, |
14 | ids::LocationCtx, PersistentHirDatabase, | 14 | ids::LocationCtx, PersistentHirDatabase, |
@@ -23,6 +23,7 @@ pub(super) struct ImportData { | |||
23 | pub(super) path: Path, | 23 | pub(super) path: Path, |
24 | pub(super) alias: Option<Name>, | 24 | pub(super) alias: Option<Name>, |
25 | pub(super) is_glob: bool, | 25 | pub(super) is_glob: bool, |
26 | pub(super) is_extern_crate: bool, | ||
26 | } | 27 | } |
27 | 28 | ||
28 | /// A set of items and imports declared inside a module, without relation to | 29 | /// A set of items and imports declared inside a module, without relation to |
@@ -186,8 +187,22 @@ impl LoweredModule { | |||
186 | ast::ModuleItemKind::UseItem(it) => { | 187 | ast::ModuleItemKind::UseItem(it) => { |
187 | self.add_use_item(source_map, it); | 188 | self.add_use_item(source_map, it); |
188 | } | 189 | } |
189 | ast::ModuleItemKind::ExternCrateItem(_) => { | 190 | ast::ModuleItemKind::ExternCrateItem(it) => { |
190 | // TODO | 191 | // Lower `extern crate x` to `use ::x`. This is kind of cheating |
192 | // and only works if we always interpret absolute paths in the | ||
193 | // 2018 style; otherwise `::x` could also refer to a module in | ||
194 | // the crate root. | ||
195 | if let Some(name_ref) = it.name_ref() { | ||
196 | let mut path = Path::from_name_ref(name_ref); | ||
197 | path.kind = PathKind::Abs; | ||
198 | let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name); | ||
199 | self.imports.alloc(ImportData { | ||
200 | path, | ||
201 | alias, | ||
202 | is_glob: false, | ||
203 | is_extern_crate: true, | ||
204 | }); | ||
205 | } | ||
191 | } | 206 | } |
192 | ast::ModuleItemKind::ConstDef(it) => { | 207 | ast::ModuleItemKind::ConstDef(it) => { |
193 | if let Some(name) = it.name() { | 208 | if let Some(name) = it.name() { |
@@ -215,6 +230,7 @@ impl LoweredModule { | |||
215 | path, | 230 | path, |
216 | alias, | 231 | alias, |
217 | is_glob: segment.is_none(), | 232 | is_glob: segment.is_none(), |
233 | is_extern_crate: false, | ||
218 | }); | 234 | }); |
219 | if let Some(segment) = segment { | 235 | if let Some(segment) = segment { |
220 | source_map.insert(import, segment) | 236 | source_map.insert(import, segment) |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 81c8a4f12..0654dbaa1 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -329,7 +329,49 @@ fn item_map_across_crates() { | |||
329 | module.module_id, | 329 | module.module_id, |
330 | " | 330 | " |
331 | Baz: t v | 331 | Baz: t v |
332 | test_crate: t | 332 | ", |
333 | ); | ||
334 | } | ||
335 | |||
336 | #[test] | ||
337 | fn extern_crate_rename() { | ||
338 | let (mut db, sr) = MockDatabase::with_files( | ||
339 | " | ||
340 | //- /main.rs | ||
341 | extern crate alloc as alloc_crate; | ||
342 | |||
343 | mod alloc; | ||
344 | mod sync; | ||
345 | |||
346 | //- /sync.rs | ||
347 | use alloc_crate::Arc; | ||
348 | |||
349 | //- /lib.rs | ||
350 | struct Arc; | ||
351 | ", | ||
352 | ); | ||
353 | let main_id = sr.files[RelativePath::new("/main.rs")]; | ||
354 | let sync_id = sr.files[RelativePath::new("/sync.rs")]; | ||
355 | let lib_id = sr.files[RelativePath::new("/lib.rs")]; | ||
356 | |||
357 | let mut crate_graph = CrateGraph::default(); | ||
358 | let main_crate = crate_graph.add_crate_root(main_id); | ||
359 | let lib_crate = crate_graph.add_crate_root(lib_id); | ||
360 | crate_graph | ||
361 | .add_dep(main_crate, "alloc".into(), lib_crate) | ||
362 | .unwrap(); | ||
363 | |||
364 | db.set_crate_graph(Arc::new(crate_graph)); | ||
365 | |||
366 | let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); | ||
367 | let krate = module.krate(&db).unwrap(); | ||
368 | let item_map = db.item_map(krate); | ||
369 | |||
370 | check_module_item_map( | ||
371 | &item_map, | ||
372 | module.module_id, | ||
373 | " | ||
374 | Arc: t v | ||
333 | ", | 375 | ", |
334 | ); | 376 | ); |
335 | } | 377 | } |
@@ -361,8 +403,6 @@ fn import_across_source_roots() { | |||
361 | 403 | ||
362 | let main_id = sr2.files[RelativePath::new("/main.rs")]; | 404 | let main_id = sr2.files[RelativePath::new("/main.rs")]; |
363 | 405 | ||
364 | eprintln!("lib = {:?}, main = {:?}", lib_id, main_id); | ||
365 | |||
366 | let mut crate_graph = CrateGraph::default(); | 406 | let mut crate_graph = CrateGraph::default(); |
367 | let main_crate = crate_graph.add_crate_root(main_id); | 407 | let main_crate = crate_graph.add_crate_root(main_id); |
368 | let lib_crate = crate_graph.add_crate_root(lib_id); | 408 | let lib_crate = crate_graph.add_crate_root(lib_id); |
@@ -381,7 +421,6 @@ fn import_across_source_roots() { | |||
381 | module.module_id, | 421 | module.module_id, |
382 | " | 422 | " |
383 | C: t v | 423 | C: t v |
384 | test_crate: t | ||
385 | ", | 424 | ", |
386 | ); | 425 | ); |
387 | } | 426 | } |
@@ -423,7 +462,6 @@ fn reexport_across_crates() { | |||
423 | module.module_id, | 462 | module.module_id, |
424 | " | 463 | " |
425 | Baz: t v | 464 | Baz: t v |
426 | test_crate: t | ||
427 | ", | 465 | ", |
428 | ); | 466 | ); |
429 | } | 467 | } |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 6c87d0df7..5ca7bacb5 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -197,7 +197,10 @@ impl Scope { | |||
197 | .entries() | 197 | .entries() |
198 | .for_each(|(name, res)| { | 198 | .for_each(|(name, res)| { |
199 | f(name.clone(), res.def.map(Resolution::Def)); | 199 | f(name.clone(), res.def.map(Resolution::Def)); |
200 | }) | 200 | }); |
201 | m.item_map.extern_prelude.iter().for_each(|(name, def)| { | ||
202 | f(name.clone(), PerNs::types(Resolution::Def(*def))); | ||
203 | }); | ||
201 | } | 204 | } |
202 | Scope::GenericParams(gp) => { | 205 | Scope::GenericParams(gp) => { |
203 | for param in &gp.params { | 206 | for param in &gp.params { |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 44514ab2b..8674b1e66 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -111,6 +111,20 @@ mod tests { | |||
111 | } | 111 | } |
112 | 112 | ||
113 | #[test] | 113 | #[test] |
114 | fn completes_extern_prelude() { | ||
115 | check_reference_completion( | ||
116 | "extern_prelude", | ||
117 | r" | ||
118 | //- /lib.rs | ||
119 | use <|>; | ||
120 | |||
121 | //- /other_crate/lib.rs | ||
122 | // nothing here | ||
123 | ", | ||
124 | ); | ||
125 | } | ||
126 | |||
127 | #[test] | ||
114 | fn completes_module_items_in_nested_modules() { | 128 | fn completes_module_items_in_nested_modules() { |
115 | check_reference_completion( | 129 | check_reference_completion( |
116 | "module_items_in_nested_modules", | 130 | "module_items_in_nested_modules", |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__extern_prelude.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__extern_prelude.snap new file mode 100644 index 000000000..d0e3a6188 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__extern_prelude.snap | |||
@@ -0,0 +1,22 @@ | |||
1 | --- | ||
2 | created: "2019-02-04T21:08:32.615556587+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "other_crate", | ||
11 | kind: Some( | ||
12 | Module | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [4; 4), | ||
20 | text_edit: None | ||
21 | } | ||
22 | ] | ||
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs index 0f2d22ab2..834b30541 100644 --- a/crates/ra_ide_api/src/mock_analysis.rs +++ b/crates/ra_ide_api/src/mock_analysis.rs | |||
@@ -86,17 +86,25 @@ impl MockAnalysis { | |||
86 | let mut change = AnalysisChange::new(); | 86 | let mut change = AnalysisChange::new(); |
87 | change.add_root(source_root, true); | 87 | change.add_root(source_root, true); |
88 | let mut crate_graph = CrateGraph::default(); | 88 | let mut crate_graph = CrateGraph::default(); |
89 | let mut root_crate = None; | ||
89 | for (i, (path, contents)) in self.files.into_iter().enumerate() { | 90 | for (i, (path, contents)) in self.files.into_iter().enumerate() { |
90 | assert!(path.starts_with('/')); | 91 | assert!(path.starts_with('/')); |
91 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | 92 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); |
92 | let file_id = FileId(i as u32 + 1); | 93 | let file_id = FileId(i as u32 + 1); |
93 | if path == "/lib.rs" || path == "/main.rs" { | 94 | if path == "/lib.rs" || path == "/main.rs" { |
94 | crate_graph.add_crate_root(file_id); | 95 | root_crate = Some(crate_graph.add_crate_root(file_id)); |
96 | } else if path.ends_with("/lib.rs") { | ||
97 | let other_crate = crate_graph.add_crate_root(file_id); | ||
98 | let crate_name = path.parent().unwrap().file_name().unwrap(); | ||
99 | if let Some(root_crate) = root_crate { | ||
100 | crate_graph | ||
101 | .add_dep(root_crate, crate_name.into(), other_crate) | ||
102 | .unwrap(); | ||
103 | } | ||
95 | } | 104 | } |
96 | change.add_file(source_root, file_id, path, Arc::new(contents)); | 105 | change.add_file(source_root, file_id, path, Arc::new(contents)); |
97 | } | 106 | } |
98 | change.set_crate_graph(crate_graph); | 107 | change.set_crate_graph(crate_graph); |
99 | // change.set_file_resolver(Arc::new(file_map)); | ||
100 | host.apply_change(change); | 108 | host.apply_change(change); |
101 | host | 109 | host |
102 | } | 110 | } |
diff --git a/crates/ra_lsp_server/src/project_model/sysroot.rs b/crates/ra_lsp_server/src/project_model/sysroot.rs index 1e0604bf5..fb4685671 100644 --- a/crates/ra_lsp_server/src/project_model/sysroot.rs +++ b/crates/ra_lsp_server/src/project_model/sysroot.rs | |||
@@ -127,6 +127,7 @@ rustc_tsan | |||
127 | syntax"; | 127 | syntax"; |
128 | 128 | ||
129 | const STD_DEPS: &str = " | 129 | const STD_DEPS: &str = " |
130 | alloc | ||
130 | alloc_jemalloc | 131 | alloc_jemalloc |
131 | alloc_system | 132 | alloc_system |
132 | core | 133 | core |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 60480c699..a8d60e882 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -970,7 +970,15 @@ impl ToOwned for ExternCrateItem { | |||
970 | } | 970 | } |
971 | 971 | ||
972 | 972 | ||
973 | impl ExternCrateItem {} | 973 | impl ExternCrateItem { |
974 | pub fn name_ref(&self) -> Option<&NameRef> { | ||
975 | super::child_opt(self) | ||
976 | } | ||
977 | |||
978 | pub fn alias(&self) -> Option<&Alias> { | ||
979 | super::child_opt(self) | ||
980 | } | ||
981 | } | ||
974 | 982 | ||
975 | // FalseKw | 983 | // FalseKw |
976 | #[derive(Debug, PartialEq, Eq, Hash)] | 984 | #[derive(Debug, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index a2ccd7cb9..2ed1fd1b8 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -601,7 +601,9 @@ Grammar( | |||
601 | "UseTreeList": ( | 601 | "UseTreeList": ( |
602 | collections: [["use_trees", "UseTree"]] | 602 | collections: [["use_trees", "UseTree"]] |
603 | ), | 603 | ), |
604 | "ExternCrateItem": (), | 604 | "ExternCrateItem": ( |
605 | options: ["NameRef", "Alias"], | ||
606 | ), | ||
605 | "ArgList": ( | 607 | "ArgList": ( |
606 | collections: [ | 608 | collections: [ |
607 | ["args", "Expr"] | 609 | ["args", "Expr"] |
diff --git a/crates/ra_syntax/src/grammar/items.rs b/crates/ra_syntax/src/grammar/items.rs index 18039cd3f..84c18a293 100644 --- a/crates/ra_syntax/src/grammar/items.rs +++ b/crates/ra_syntax/src/grammar/items.rs | |||
@@ -247,7 +247,7 @@ fn extern_crate_item(p: &mut Parser) { | |||
247 | p.bump(); | 247 | p.bump(); |
248 | assert!(p.at(CRATE_KW)); | 248 | assert!(p.at(CRATE_KW)); |
249 | p.bump(); | 249 | p.bump(); |
250 | name(p); | 250 | name_ref(p); |
251 | opt_alias(p); | 251 | opt_alias(p); |
252 | p.expect(SEMI); | 252 | p.expect(SEMI); |
253 | } | 253 | } |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt index 7ffdc7fbd..a7b428787 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt | |||
@@ -4,7 +4,7 @@ SOURCE_FILE@[0; 18) | |||
4 | WHITESPACE@[6; 7) | 4 | WHITESPACE@[6; 7) |
5 | CRATE_KW@[7; 12) | 5 | CRATE_KW@[7; 12) |
6 | WHITESPACE@[12; 13) | 6 | WHITESPACE@[12; 13) |
7 | NAME@[13; 16) | 7 | NAME_REF@[13; 16) |
8 | IDENT@[13; 16) "foo" | 8 | IDENT@[13; 16) "foo" |
9 | SEMI@[16; 17) | 9 | SEMI@[16; 17) |
10 | WHITESPACE@[17; 18) | 10 | WHITESPACE@[17; 18) |
diff --git a/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt b/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt index 5adf3f276..5558d952e 100644 --- a/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt +++ b/crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt | |||
@@ -4,7 +4,7 @@ SOURCE_FILE@[0; 43) | |||
4 | WHITESPACE@[6; 7) | 4 | WHITESPACE@[6; 7) |
5 | CRATE_KW@[7; 12) | 5 | CRATE_KW@[7; 12) |
6 | WHITESPACE@[12; 13) | 6 | WHITESPACE@[12; 13) |
7 | NAME@[13; 16) | 7 | NAME_REF@[13; 16) |
8 | IDENT@[13; 16) "foo" | 8 | IDENT@[13; 16) "foo" |
9 | SEMI@[16; 17) | 9 | SEMI@[16; 17) |
10 | WHITESPACE@[17; 18) | 10 | WHITESPACE@[17; 18) |
@@ -13,7 +13,7 @@ SOURCE_FILE@[0; 43) | |||
13 | WHITESPACE@[24; 25) | 13 | WHITESPACE@[24; 25) |
14 | CRATE_KW@[25; 30) | 14 | CRATE_KW@[25; 30) |
15 | WHITESPACE@[30; 31) | 15 | WHITESPACE@[30; 31) |
16 | NAME@[31; 34) | 16 | NAME_REF@[31; 34) |
17 | IDENT@[31; 34) "foo" | 17 | IDENT@[31; 34) "foo" |
18 | WHITESPACE@[34; 35) | 18 | WHITESPACE@[34; 35) |
19 | ALIAS@[35; 41) | 19 | ALIAS@[35; 41) |