• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::*;
2 
3 pub(super) const PATH_FIRST: TokenSet =
4     TokenSet::new(&[IDENT, T![self], T![super], T![crate], T![Self], T![:], T![<]]);
5 
is_path_start(p: &Parser<'_>) -> bool6 pub(super) fn is_path_start(p: &Parser<'_>) -> bool {
7     is_use_path_start(p) || p.at(T![<]) || p.at(T![Self])
8 }
9 
is_use_path_start(p: &Parser<'_>) -> bool10 pub(super) fn is_use_path_start(p: &Parser<'_>) -> bool {
11     match p.current() {
12         IDENT | T![self] | T![super] | T![crate] => true,
13         T![:] if p.at(T![::]) => true,
14         _ => false,
15     }
16 }
17 
use_path(p: &mut Parser<'_>)18 pub(super) fn use_path(p: &mut Parser<'_>) {
19     path(p, Mode::Use);
20 }
21 
type_path(p: &mut Parser<'_>)22 pub(crate) fn type_path(p: &mut Parser<'_>) {
23     path(p, Mode::Type);
24 }
25 
expr_path(p: &mut Parser<'_>)26 pub(super) fn expr_path(p: &mut Parser<'_>) {
27     path(p, Mode::Expr);
28 }
29 
type_path_for_qualifier( p: &mut Parser<'_>, qual: CompletedMarker, ) -> CompletedMarker30 pub(crate) fn type_path_for_qualifier(
31     p: &mut Parser<'_>,
32     qual: CompletedMarker,
33 ) -> CompletedMarker {
34     path_for_qualifier(p, Mode::Type, qual)
35 }
36 
37 #[derive(Clone, Copy, Eq, PartialEq)]
38 enum Mode {
39     Use,
40     Type,
41     Expr,
42 }
43 
path(p: &mut Parser<'_>, mode: Mode)44 fn path(p: &mut Parser<'_>, mode: Mode) {
45     let path = p.start();
46     path_segment(p, mode, true);
47     let qual = path.complete(p, PATH);
48     path_for_qualifier(p, mode, qual);
49 }
50 
path_for_qualifier( p: &mut Parser<'_>, mode: Mode, mut qual: CompletedMarker, ) -> CompletedMarker51 fn path_for_qualifier(
52     p: &mut Parser<'_>,
53     mode: Mode,
54     mut qual: CompletedMarker,
55 ) -> CompletedMarker {
56     loop {
57         let use_tree = mode == Mode::Use && matches!(p.nth(2), T![*] | T!['{']);
58         if p.at(T![::]) && !use_tree {
59             let path = qual.precede(p);
60             p.bump(T![::]);
61             path_segment(p, mode, false);
62             let path = path.complete(p, PATH);
63             qual = path;
64         } else {
65             return qual;
66         }
67     }
68 }
69 
70 const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
71     items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]]));
72 const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
73 
path_segment(p: &mut Parser<'_>, mode: Mode, first: bool)74 fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
75     let m = p.start();
76     // test qual_paths
77     // type X = <A as B>::Output;
78     // fn foo() { <usize as Default>::default(); }
79     if first && p.eat(T![<]) {
80         // test_err angled_path_without_qual
81         // type X = <()>;
82         // type Y = <A as B>;
83         types::type_(p);
84         if p.eat(T![as]) {
85             if is_use_path_start(p) {
86                 types::path_type(p);
87             } else {
88                 p.error("expected a trait");
89             }
90         }
91         p.expect(T![>]);
92         if !p.at(T![::]) {
93             p.error("expected `::`");
94         }
95     } else {
96         let empty = if first {
97             p.eat(T![::]);
98             false
99         } else {
100             true
101         };
102         match p.current() {
103             IDENT => {
104                 name_ref(p);
105                 opt_path_type_args(p, mode);
106             }
107             // test crate_path
108             // use crate::foo;
109             T![self] | T![super] | T![crate] | T![Self] => {
110                 let m = p.start();
111                 p.bump_any();
112                 m.complete(p, NAME_REF);
113             }
114             _ => {
115                 let recover_set = match mode {
116                     Mode::Use => items::ITEM_RECOVERY_SET,
117                     Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
118                     Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
119                 };
120                 p.err_recover("expected identifier", recover_set);
121                 if empty {
122                     // test_err empty_segment
123                     // use crate::;
124                     m.abandon(p);
125                     return;
126                 }
127             }
128         };
129     }
130     m.complete(p, PATH_SEGMENT);
131 }
132 
opt_path_type_args(p: &mut Parser<'_>, mode: Mode)133 fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
134     match mode {
135         Mode::Use => {}
136         Mode::Type => {
137             // test typepathfn_with_coloncolon
138             // type F = Start::(Middle) -> (Middle)::End;
139             // type GenericArg = S<Start(Middle)::End>;
140             if p.at(T![::]) && p.nth_at(2, T!['(']) {
141                 p.bump(T![::]);
142             }
143             // test path_fn_trait_args
144             // type F = Box<Fn(i32) -> ()>;
145             if p.at(T!['(']) {
146                 params::param_list_fn_trait(p);
147                 opt_ret_type(p);
148             } else {
149                 generic_args::opt_generic_arg_list(p, false);
150             }
151         }
152         Mode::Expr => generic_args::opt_generic_arg_list(p, true),
153     }
154 }
155