]>
Commit | Line | Data |
---|---|---|
064997fb FG |
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 | ||
6 | pub(super) fn is_path_start(p: &Parser<'_>) -> bool { | |
7 | is_use_path_start(p) || p.at(T![<]) || p.at(T![Self]) | |
8 | } | |
9 | ||
10 | 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 | ||
18 | pub(super) fn use_path(p: &mut Parser<'_>) { | |
19 | path(p, Mode::Use); | |
20 | } | |
21 | ||
22 | pub(crate) fn type_path(p: &mut Parser<'_>) { | |
23 | path(p, Mode::Type); | |
24 | } | |
25 | ||
26 | pub(super) fn expr_path(p: &mut Parser<'_>) { | |
27 | path(p, Mode::Expr); | |
28 | } | |
29 | ||
30 | 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 | ||
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 | ||
51 | 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 | fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) { | |
71 | let m = p.start(); | |
72 | // test qual_paths | |
73 | // type X = <A as B>::Output; | |
74 | // fn foo() { <usize as Default>::default(); } | |
75 | if first && p.eat(T![<]) { | |
76 | types::type_(p); | |
77 | if p.eat(T![as]) { | |
78 | if is_use_path_start(p) { | |
79 | types::path_type(p); | |
80 | } else { | |
81 | p.error("expected a trait"); | |
82 | } | |
83 | } | |
84 | p.expect(T![>]); | |
85 | } else { | |
86 | let mut empty = true; | |
87 | if first { | |
88 | p.eat(T![::]); | |
89 | empty = false; | |
90 | } | |
91 | match p.current() { | |
92 | IDENT => { | |
93 | name_ref(p); | |
94 | opt_path_type_args(p, mode); | |
95 | } | |
96 | // test crate_path | |
97 | // use crate::foo; | |
98 | T![self] | T![super] | T![crate] | T![Self] => { | |
99 | let m = p.start(); | |
100 | p.bump_any(); | |
101 | m.complete(p, NAME_REF); | |
102 | } | |
103 | _ => { | |
104 | p.err_recover("expected identifier", items::ITEM_RECOVERY_SET); | |
105 | if empty { | |
106 | // test_err empty_segment | |
107 | // use crate::; | |
108 | m.abandon(p); | |
109 | return; | |
110 | } | |
111 | } | |
112 | }; | |
113 | } | |
114 | m.complete(p, PATH_SEGMENT); | |
115 | } | |
116 | ||
117 | fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) { | |
118 | match mode { | |
119 | Mode::Use => {} | |
120 | Mode::Type => { | |
f2b60f7d FG |
121 | // test typepathfn_with_coloncolon |
122 | // type F = Start::(Middle) -> (Middle)::End; | |
123 | if p.at(T![::]) && p.nth_at(2, T!['(']) { | |
124 | p.bump(T![::]); | |
125 | } | |
064997fb FG |
126 | // test path_fn_trait_args |
127 | // type F = Box<Fn(i32) -> ()>; | |
128 | if p.at(T!['(']) { | |
129 | params::param_list_fn_trait(p); | |
130 | opt_ret_type(p); | |
131 | } else { | |
132 | generic_args::opt_generic_arg_list(p, false); | |
133 | } | |
134 | } | |
135 | Mode::Expr => generic_args::opt_generic_arg_list(p, true), | |
136 | } | |
137 | } |