Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/paths.rs')
-rw-r--r--crates/parser/src/grammar/paths.rs175
1 files changed, 109 insertions, 66 deletions
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs
index 09db921803..3410505cd4 100644
--- a/crates/parser/src/grammar/paths.rs
+++ b/crates/parser/src/grammar/paths.rs
@@ -19,6 +19,14 @@ pub(super) fn use_path(p: &mut Parser<'_>) {
path(p, Mode::Use);
}
+pub(super) fn vis_path(p: &mut Parser<'_>) {
+ path(p, Mode::Vis);
+}
+
+pub(super) fn attr_path(p: &mut Parser<'_>) {
+ path(p, Mode::Attr);
+}
+
pub(crate) fn type_path(p: &mut Parser<'_>) {
path(p, Mode::Type);
}
@@ -37,15 +45,20 @@ pub(crate) fn type_path_for_qualifier(
#[derive(Clone, Copy, Eq, PartialEq)]
enum Mode {
Use,
+ Attr,
Type,
Expr,
+ Vis,
}
-fn path(p: &mut Parser<'_>, mode: Mode) {
+fn path(p: &mut Parser<'_>, mode: Mode) -> Option<CompletedMarker> {
let path = p.start();
- path_segment(p, mode, true);
+ if path_segment(p, mode, true).is_none() {
+ path.abandon(p);
+ return None;
+ }
let qual = path.complete(p, PATH);
- path_for_qualifier(p, mode, qual);
+ Some(path_for_qualifier(p, mode, qual))
}
fn path_for_qualifier(
@@ -71,7 +84,7 @@ const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]]));
const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
-fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
+fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
let m = p.start();
// test qual_paths
// type X = <A as B>::Output;
@@ -93,75 +106,105 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
p.error("expected `::`");
}
} else {
- let empty = if first {
- p.eat(T![::]);
- false
- } else {
- true
- };
- match p.current() {
- IDENT => {
- name_ref(p);
- opt_path_type_args(p, mode);
- }
+ let mut empty = if first { !p.eat(T![::]) } else { true };
+ if p.at_ts(PATH_NAME_REF_KINDS) {
// test crate_path
// use crate::foo;
- T![self] | T![super] | T![crate] | T![Self] => {
- let m = p.start();
- p.bump_any();
- m.complete(p, NAME_REF);
- }
- _ => {
- let recover_set = match mode {
- Mode::Use => items::ITEM_RECOVERY_SET,
- Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
- Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
- };
- p.err_recover("expected identifier", recover_set);
- if empty {
- // test_err empty_segment
- // use crate::;
- m.abandon(p);
- return;
+ name_ref_mod_path(p);
+ opt_path_args(p, mode);
+ } else {
+ let recover_set = match mode {
+ Mode::Use => items::ITEM_RECOVERY_SET,
+ Mode::Attr => {
+ items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]]))
}
+ Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])),
+ Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
+ Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
+ };
+ empty &= p.err_recover(
+ "expected identifier, `self`, `super`, `crate`, or `Self`",
+ recover_set,
+ );
+ if empty {
+ // test_err empty_segment
+ // use crate::;
+ m.abandon(p);
+ return None;
}
- };
+ }
}
- m.complete(p, PATH_SEGMENT);
+ Some(m.complete(p, PATH_SEGMENT))
}
-fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
+pub(crate) fn opt_path_type_args(p: &mut Parser<'_>) {
+ // test typepathfn_with_coloncolon
+ // type F = Start::(Middle) -> (Middle)::End;
+ // type GenericArg = S<Start(Middle)::End>;
+ let m;
+ if p.at(T![::]) && matches!(p.nth(2), T![<] | T!['(']) {
+ m = p.start();
+ p.bump(T![::]);
+ } else if (p.current() == T![<] && p.nth(1) != T![=]) || p.current() == T!['('] {
+ m = p.start();
+ } else {
+ return;
+ }
+ let current = p.current();
+ if current == T![<] {
+ // test_err generic_arg_list_recover
+ // type T = T<0, ,T>;
+ // type T = T::<0, ,T>;
+ delimited(
+ p,
+ T![<],
+ T![>],
+ T![,],
+ || "expected generic argument".into(),
+ generic_args::GENERIC_ARG_FIRST,
+ generic_args::generic_arg,
+ );
+ m.complete(p, GENERIC_ARG_LIST);
+ } else if p.nth_at(1, T![..]) {
+ // test return_type_syntax_in_path
+ // fn foo<T>()
+ // where
+ // T::method(..): Send,
+ // method(..): Send,
+ // method::(..): Send,
+ // {}
+ p.bump(T!['(']);
+ p.bump(T![..]);
+ p.expect(T![')']);
+ m.complete(p, RETURN_TYPE_SYNTAX);
+ } else {
+ // test path_fn_trait_args
+ // type F = Box<Fn(i32) -> ()>;
+ // type F = Box<::Fn(i32) -> ()>;
+ // type F = Box<Fn::(i32) -> ()>;
+ // type F = Box<::Fn::(i32) -> ()>;
+ delimited(
+ p,
+ T!['('],
+ T![')'],
+ T![,],
+ || "expected type".into(),
+ types::TYPE_FIRST,
+ |p| {
+ let progress = types::TYPE_FIRST.contains(p.current());
+ generic_args::type_arg(p);
+ progress
+ },
+ );
+ m.complete(p, PARENTHESIZED_ARG_LIST);
+ opt_ret_type(p);
+ }
+}
+
+fn opt_path_args(p: &mut Parser<'_>, mode: Mode) {
match mode {
- Mode::Use => {}
- Mode::Type => {
- // test typepathfn_with_coloncolon
- // type F = Start::(Middle) -> (Middle)::End;
- // type GenericArg = S<Start(Middle)::End>;
- if p.at(T![::]) && p.nth_at(2, T!['(']) {
- p.bump(T![::]);
- }
- if p.at(T!['(']) {
- if p.nth_at(1, T![..]) {
- // test return_type_syntax_in_path
- // fn foo<T>()
- // where
- // T::method(..): Send,
- // {}
- let rtn = p.start();
- p.bump(T!['(']);
- p.bump(T![..]);
- p.expect(T![')']);
- rtn.complete(p, RETURN_TYPE_SYNTAX);
- } else {
- // test path_fn_trait_args
- // type F = Box<Fn(i32) -> ()>;
- params::param_list_fn_trait(p);
- opt_ret_type(p);
- }
- } else {
- generic_args::opt_generic_arg_list(p, false);
- }
- }
- Mode::Expr => generic_args::opt_generic_arg_list(p, true),
+ Mode::Use | Mode::Attr | Mode::Vis => {}
+ Mode::Type => opt_path_type_args(p),
+ Mode::Expr => generic_args::opt_generic_arg_list_expr(p),
}
}