]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / parser / src / grammar / paths.rs
CommitLineData
064997fb
FG
1use super::*;
2
3pub(super) const PATH_FIRST: TokenSet =
4 TokenSet::new(&[IDENT, T![self], T![super], T![crate], T![Self], T![:], T![<]]);
5
6pub(super) fn is_path_start(p: &Parser<'_>) -> bool {
7 is_use_path_start(p) || p.at(T![<]) || p.at(T![Self])
8}
9
10pub(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
18pub(super) fn use_path(p: &mut Parser<'_>) {
19 path(p, Mode::Use);
20}
21
22pub(crate) fn type_path(p: &mut Parser<'_>) {
23 path(p, Mode::Type);
24}
25
26pub(super) fn expr_path(p: &mut Parser<'_>) {
27 path(p, Mode::Expr);
28}
29
30pub(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)]
38enum Mode {
39 Use,
40 Type,
41 Expr,
42}
43
44fn 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
51fn 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
70fn 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
117fn 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}