diff options
| author | Zac Pullar-Strecker <[email protected]> | 2020-08-24 10:19:53 +0100 |
|---|---|---|
| committer | Zac Pullar-Strecker <[email protected]> | 2020-08-24 10:20:13 +0100 |
| commit | 7bbca7a1b3f9293d2f5cc5745199bc5f8396f2f0 (patch) | |
| tree | bdb47765991cb973b2cd5481a088fac636bd326c /crates/ra_parser/src/grammar/items/use_item.rs | |
| parent | ca464650eeaca6195891199a93f4f76cf3e7e697 (diff) | |
| parent | e65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff) | |
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Diffstat (limited to 'crates/ra_parser/src/grammar/items/use_item.rs')
| -rw-r--r-- | crates/ra_parser/src/grammar/items/use_item.rs | 132 |
1 files changed, 0 insertions, 132 deletions
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs deleted file mode 100644 index 8e836a77e..000000000 --- a/crates/ra_parser/src/grammar/items/use_item.rs +++ /dev/null | |||
| @@ -1,132 +0,0 @@ | |||
| 1 | //! FIXME: write short doc here | ||
| 2 | |||
| 3 | use super::*; | ||
| 4 | |||
| 5 | pub(super) fn use_item(p: &mut Parser, m: Marker) { | ||
| 6 | assert!(p.at(T![use])); | ||
| 7 | p.bump(T![use]); | ||
| 8 | use_tree(p, true); | ||
| 9 | p.expect(T![;]); | ||
| 10 | m.complete(p, USE); | ||
| 11 | } | ||
| 12 | |||
| 13 | /// Parse a use 'tree', such as `some::path` in `use some::path;` | ||
| 14 | /// Note that this is called both by `use_item` and `use_tree_list`, | ||
| 15 | /// so handles both `some::path::{inner::path}` and `inner::path` in | ||
| 16 | /// `use some::path::{inner::path};` | ||
| 17 | fn use_tree(p: &mut Parser, top_level: bool) { | ||
| 18 | let m = p.start(); | ||
| 19 | match p.current() { | ||
| 20 | // Finish the use_tree for cases of e.g. | ||
| 21 | // `use some::path::{self, *};` or `use *;` | ||
| 22 | // This does not handle cases such as `use some::path::*` | ||
| 23 | // N.B. in Rust 2015 `use *;` imports all from crate root | ||
| 24 | // however in Rust 2018 `use *;` errors: ('cannot glob-import all possible crates') | ||
| 25 | // FIXME: Add this error (if not out of scope) | ||
| 26 | |||
| 27 | // test use_star | ||
| 28 | // use *; | ||
| 29 | // use ::*; | ||
| 30 | // use some::path::{*}; | ||
| 31 | // use some::path::{::*}; | ||
| 32 | T![*] => p.bump(T![*]), | ||
| 33 | T![:] if p.at(T![::]) && p.nth(2) == T![*] => { | ||
| 34 | // Parse `use ::*;`, which imports all from the crate root in Rust 2015 | ||
| 35 | // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`) | ||
| 36 | // but still parses and errors later: ('crate root in paths can only be used in start position') | ||
| 37 | // FIXME: Add this error (if not out of scope) | ||
| 38 | // In Rust 2018, it is always invalid (see above) | ||
| 39 | p.bump(T![::]); | ||
| 40 | p.bump(T![*]); | ||
| 41 | } | ||
| 42 | // Open a use tree list | ||
| 43 | // Handles cases such as `use {some::path};` or `{inner::path}` in | ||
| 44 | // `use some::path::{{inner::path}, other::path}` | ||
| 45 | |||
| 46 | // test use_tree_list | ||
| 47 | // use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) | ||
| 48 | // use {path::from::root}; // Rust 2015 | ||
| 49 | // use ::{some::arbritrary::path}; // Rust 2015 | ||
| 50 | // use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting | ||
| 51 | T!['{'] => { | ||
| 52 | use_tree_list(p); | ||
| 53 | } | ||
| 54 | T![:] if p.at(T![::]) && p.nth(2) == T!['{'] => { | ||
| 55 | p.bump(T![::]); | ||
| 56 | use_tree_list(p); | ||
| 57 | } | ||
| 58 | // Parse a 'standard' path. | ||
| 59 | // Also handles aliases (e.g. `use something as something_else`) | ||
| 60 | |||
| 61 | // test use_path | ||
| 62 | // use ::crate_name; // Rust 2018 - All flavours | ||
| 63 | // use crate_name; // Rust 2018 - Anchored paths | ||
| 64 | // use item_in_scope_or_crate_name; // Rust 2018 - Uniform Paths | ||
| 65 | // | ||
| 66 | // use self::module::Item; | ||
| 67 | // use crate::Item; | ||
| 68 | // use self::some::Struct; | ||
| 69 | // use crate_name::some_item; | ||
| 70 | _ if paths::is_use_path_start(p) => { | ||
| 71 | paths::use_path(p); | ||
| 72 | match p.current() { | ||
| 73 | T![as] => { | ||
| 74 | // test use_alias | ||
| 75 | // use some::path as some_name; | ||
| 76 | // use some::{ | ||
| 77 | // other::path as some_other_name, | ||
| 78 | // different::path as different_name, | ||
| 79 | // yet::another::path, | ||
| 80 | // running::out::of::synonyms::for_::different::* | ||
| 81 | // }; | ||
| 82 | // use Trait as _; | ||
| 83 | opt_alias(p); | ||
| 84 | } | ||
| 85 | T![:] if p.at(T![::]) => { | ||
| 86 | p.bump(T![::]); | ||
| 87 | match p.current() { | ||
| 88 | T![*] => { | ||
| 89 | p.bump(T![*]); | ||
| 90 | } | ||
| 91 | // test use_tree_list_after_path | ||
| 92 | // use crate::{Item}; | ||
| 93 | // use self::{Item}; | ||
| 94 | T!['{'] => use_tree_list(p), | ||
| 95 | _ => { | ||
| 96 | // is this unreachable? | ||
| 97 | p.error("expected `{` or `*`"); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | _ => (), | ||
| 102 | } | ||
| 103 | } | ||
| 104 | _ => { | ||
| 105 | m.abandon(p); | ||
| 106 | let msg = "expected one of `*`, `::`, `{`, `self`, `super` or an identifier"; | ||
| 107 | if top_level { | ||
| 108 | p.err_recover(msg, ITEM_RECOVERY_SET); | ||
| 109 | } else { | ||
| 110 | // if we are parsing a nested tree, we have to eat a token to | ||
| 111 | // main balanced `{}` | ||
| 112 | p.err_and_bump(msg); | ||
| 113 | } | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | m.complete(p, USE_TREE); | ||
| 118 | } | ||
| 119 | |||
| 120 | pub(crate) fn use_tree_list(p: &mut Parser) { | ||
| 121 | assert!(p.at(T!['{'])); | ||
| 122 | let m = p.start(); | ||
| 123 | p.bump(T!['{']); | ||
| 124 | while !p.at(EOF) && !p.at(T!['}']) { | ||
| 125 | use_tree(p, false); | ||
| 126 | if !p.at(T!['}']) { | ||
| 127 | p.expect(T![,]); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | p.expect(T!['}']); | ||
| 131 | m.complete(p, USE_TREE_LIST); | ||
| 132 | } | ||
