feat: complete raw, const keyword

This commit is contained in:
lh123 2025-01-16 18:05:30 +08:00
parent 7d337c7f35
commit 9809143562
6 changed files with 144 additions and 8 deletions

View file

@ -581,10 +581,7 @@ impl ExprCollector<'_> {
let mutability = if raw_tok {
if e.mut_token().is_some() {
Mutability::Mut
} else if e.const_token().is_some() {
Mutability::Shared
} else {
never!("parser only remaps to raw_token() if matching mutability token follows");
Mutability::Shared
}
} else {

View file

@ -69,8 +69,25 @@ pub(crate) fn complete_expr_path(
..
} = expr_ctx;
let wants_mut_token =
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
let has_raw_token =
ref_expr_parent.as_ref().map(|it| it.raw_token().is_some()).unwrap_or(false);
let has_const_token =
ref_expr_parent.as_ref().map(|it| it.const_token().is_some()).unwrap_or(false);
let has_mut_token =
ref_expr_parent.as_ref().map(|it| it.mut_token().is_some()).unwrap_or(false);
let wants_raw_token = ref_expr_parent.is_some() && !has_raw_token;
let wants_const_token =
ref_expr_parent.is_some() && has_raw_token && !has_const_token && !has_mut_token;
let wants_mut_token = if ref_expr_parent.is_some() {
if has_raw_token {
!has_const_token && !has_mut_token
} else {
!has_mut_token
}
} else {
false
};
let scope_def_applicable = |def| match def {
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false,
@ -354,6 +371,12 @@ pub(crate) fn complete_expr_path(
add_keyword("else if", "else if $1 {\n $0\n}");
}
if wants_raw_token {
add_keyword("raw", "raw ");
}
if wants_const_token {
add_keyword("const", "const ");
}
if wants_mut_token {
add_keyword("mut", "mut ");
}

View file

@ -66,6 +66,7 @@ fn baz() {
kw loop
kw match
kw mut
kw raw
kw return
kw self::
kw true
@ -436,6 +437,94 @@ fn completes_in_let_initializer() {
)
}
#[test]
fn completes_after_ref_expr() {
check(
r#"fn main() { let _ = &$0 }"#,
expect![[r#"
fn main() fn()
bt u32 u32
kw crate::
kw false
kw for
kw if
kw if let
kw loop
kw match
kw mut
kw raw
kw return
kw self::
kw true
kw unsafe
kw while
kw while let
"#]],
);
check(
r#"fn main() { let _ = &raw $0 }"#,
expect![[r#"
fn main() fn()
bt u32 u32
kw const
kw crate::
kw false
kw for
kw if
kw if let
kw loop
kw match
kw mut
kw return
kw self::
kw true
kw unsafe
kw while
kw while let
"#]],
);
check(
r#"fn main() { let _ = &raw const $0 }"#,
expect![[r#"
fn main() fn()
bt u32 u32
kw crate::
kw false
kw for
kw if
kw if let
kw loop
kw match
kw return
kw self::
kw true
kw unsafe
kw while
kw while let
"#]],
);
check(
r#"fn main() { let _ = &raw mut $0 }"#,
expect![[r#"
fn main() fn()
bt u32 u32
kw crate::
kw false
kw for
kw if
kw if let
kw loop
kw match
kw return
kw self::
kw true
kw unsafe
kw while
kw while let
"#]],
)
}
#[test]
fn struct_initializer_field_expr() {
check(

View file

@ -339,13 +339,20 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik
// // raw reference operator
// let _ = &raw mut foo;
// let _ = &raw const foo;
// let _ = &raw foo;
// }
T![&] => {
m = p.start();
p.bump(T![&]);
if p.at_contextual_kw(T![raw]) && [T![mut], T![const]].contains(&p.nth(1)) {
p.bump_remap(T![raw]);
p.bump_any();
if p.at_contextual_kw(T![raw]) {
if [T![mut], T![const]].contains(&p.nth(1)) {
p.bump_remap(T![raw]);
p.bump_any();
} else if p.nth_at(1, SyntaxKind::IDENT) {
// we treat raw as keyword in this case
// &raw foo;
p.bump_remap(T![raw]);
}
} else {
p.eat(T![mut]);
}

View file

@ -134,6 +134,25 @@ SOURCE_FILE
NAME_REF
IDENT "foo"
SEMICOLON ";"
WHITESPACE "\n "
LET_STMT
LET_KW "let"
WHITESPACE " "
WILDCARD_PAT
UNDERSCORE "_"
WHITESPACE " "
EQ "="
WHITESPACE " "
REF_EXPR
AMP "&"
RAW_KW "raw"
WHITESPACE " "
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "foo"
SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -7,4 +7,5 @@ fn foo() {
// raw reference operator
let _ = &raw mut foo;
let _ = &raw const foo;
let _ = &raw foo;
}