aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/items/use_item.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/items/use_item.rs')
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
new file mode 100644
index 000000000..5111d37eb
--- /dev/null
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -0,0 +1,121 @@
1use super::*;
2
3pub(super) fn use_item(p: &mut Parser) {
4 assert!(p.at(USE_KW));
5 p.bump();
6 use_tree(p);
7 p.expect(SEMI);
8}
9
10/// Parse a use 'tree', such as `some::path` in `use some::path;`
11/// Note that this is called both by `use_item` and `use_tree_list`,
12/// so handles both `some::path::{inner::path}` and `inner::path` in
13/// `use some::path::{inner::path};`
14fn use_tree(p: &mut Parser) {
15 let la = p.nth(1);
16 let m = p.start();
17 match (p.current(), la) {
18 // Finish the use_tree for cases of e.g.
19 // `use some::path::{self, *};` or `use *;`
20 // This does not handle cases such as `use some::path::*`
21 // N.B. in Rust 2015 `use *;` imports all from crate root
22 // however in Rust 2018 `use *;` errors: ('cannot glob-import all possible crates')
23 // TODO: Add this error (if not out of scope)
24
25 // test use_star
26 // use *;
27 // use ::*;
28 // use some::path::{*};
29 // use some::path::{::*};
30 (STAR, _) => p.bump(),
31 (COLONCOLON, STAR) => {
32 // Parse `use ::*;`, which imports all from the crate root in Rust 2015
33 // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`)
34 // but still parses and errors later: ('crate root in paths can only be used in start position')
35 // TODO: Add this error (if not out of scope)
36 // In Rust 2018, it is always invalid (see above)
37 p.bump();
38 p.bump();
39 }
40 // Open a use tree list
41 // Handles cases such as `use {some::path};` or `{inner::path}` in
42 // `use some::path::{{inner::path}, other::path}`
43
44 // test use_tree_list
45 // use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`)
46 // use {path::from::root}; // Rust 2015
47 // use ::{some::arbritrary::path}; // Rust 2015
48 // use ::{{{crate::export}}}; // Nonsensical but perfectly legal nestnig
49 (L_CURLY, _) | (COLONCOLON, L_CURLY) => {
50 if p.at(COLONCOLON) {
51 p.bump();
52 }
53 use_tree_list(p);
54 }
55 // Parse a 'standard' path.
56 // Also handles aliases (e.g. `use something as something_else`)
57
58 // test use_path
59 // use ::crate_name; // Rust 2018 - All flavours
60 // use crate_name; // Rust 2018 - Anchored paths
61 // use item_in_scope_or_crate_name; // Rust 2018 - Uniform Paths
62 //
63 // use self::module::Item;
64 // use crate::Item;
65 // use self::some::Struct;
66 // use crate_name::some_item;
67 _ if paths::is_path_start(p) => {
68 paths::use_path(p);
69 match p.current() {
70 AS_KW => {
71 // test use_alias
72 // use some::path as some_name;
73 // use some::{
74 // other::path as some_other_name,
75 // different::path as different_name,
76 // yet::another::path,
77 // running::out::of::synonyms::for_::different::*
78 // };
79 opt_alias(p);
80 }
81 COLONCOLON => {
82 p.bump();
83 match p.current() {
84 STAR => {
85 p.bump();
86 }
87 // test use_tree_list_after_path
88 // use crate::{Item};
89 // use self::{Item};
90 L_CURLY => use_tree_list(p),
91 _ => {
92 // is this unreachable?
93 p.error("expected `{` or `*`");
94 }
95 }
96 }
97 _ => (),
98 }
99 }
100 _ => {
101 m.abandon(p);
102 p.err_and_bump("expected one of `*`, `::`, `{`, `self`, `super` or an indentifier");
103 return;
104 }
105 }
106 m.complete(p, USE_TREE);
107}
108
109pub(crate) fn use_tree_list(p: &mut Parser) {
110 assert!(p.at(L_CURLY));
111 let m = p.start();
112 p.bump();
113 while !p.at(EOF) && !p.at(R_CURLY) {
114 use_tree(p);
115 if !p.at(R_CURLY) {
116 p.expect(COMMA);
117 }
118 }
119 p.expect(R_CURLY);
120 m.complete(p, USE_TREE_LIST);
121}