Skip to content

Commit 903bc81

Browse files
authored
Merge pull request #18952 from lh123/add-raw-keyword-complete
feat: complete raw, const keyword
2 parents 1f717b0 + a282733 commit 903bc81

File tree

8 files changed

+168
-8
lines changed

8 files changed

+168
-8
lines changed

Diff for: crates/hir-def/src/body/lower.rs

-3
Original file line numberDiff line numberDiff line change
@@ -581,10 +581,7 @@ impl ExprCollector<'_> {
581581
let mutability = if raw_tok {
582582
if e.mut_token().is_some() {
583583
Mutability::Mut
584-
} else if e.const_token().is_some() {
585-
Mutability::Shared
586584
} else {
587-
never!("parser only remaps to raw_token() if matching mutability token follows");
588585
Mutability::Shared
589586
}
590587
} else {

Diff for: crates/ide-completion/src/completions/expr.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,31 @@ pub(crate) fn complete_expr_path(
6262
in_condition,
6363
incomplete_let,
6464
ref ref_expr_parent,
65+
after_amp,
6566
ref is_func_update,
6667
ref innermost_ret_ty,
6768
ref impl_,
6869
in_match_guard,
6970
..
7071
} = expr_ctx;
7172

72-
let wants_mut_token =
73-
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
73+
let (has_raw_token, has_const_token, has_mut_token) = ref_expr_parent
74+
.as_ref()
75+
.map(|it| (it.raw_token().is_some(), it.const_token().is_some(), it.mut_token().is_some()))
76+
.unwrap_or((false, false, false));
77+
78+
let wants_raw_token = ref_expr_parent.is_some() && !has_raw_token && after_amp;
79+
let wants_const_token =
80+
ref_expr_parent.is_some() && has_raw_token && !has_const_token && !has_mut_token;
81+
let wants_mut_token = if ref_expr_parent.is_some() {
82+
if has_raw_token {
83+
!has_const_token && !has_mut_token
84+
} else {
85+
!has_mut_token
86+
}
87+
} else {
88+
false
89+
};
7490

7591
let scope_def_applicable = |def| match def {
7692
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false,
@@ -354,6 +370,12 @@ pub(crate) fn complete_expr_path(
354370
add_keyword("else if", "else if $1 {\n $0\n}");
355371
}
356372

373+
if wants_raw_token {
374+
add_keyword("raw", "raw ");
375+
}
376+
if wants_const_token {
377+
add_keyword("const", "const ");
378+
}
357379
if wants_mut_token {
358380
add_keyword("mut", "mut ");
359381
}

Diff for: crates/ide-completion/src/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ pub(crate) struct PathExprCtx {
146146
pub(crate) in_condition: bool,
147147
pub(crate) incomplete_let: bool,
148148
pub(crate) ref_expr_parent: Option<ast::RefExpr>,
149+
pub(crate) after_amp: bool,
149150
/// The surrounding RecordExpression we are completing a functional update
150151
pub(crate) is_func_update: Option<ast::RecordExpr>,
151152
pub(crate) self_param: Option<hir::SelfParam>,

Diff for: crates/ide-completion/src/context/analysis.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,9 @@ fn classify_name_ref(
11511151
let after_if_expr = after_if_expr(it.clone());
11521152
let ref_expr_parent =
11531153
path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
1154+
let after_amp = non_trivia_sibling(it.clone().into(), Direction::Prev)
1155+
.map(|it| it.kind() == SyntaxKind::AMP)
1156+
.unwrap_or(false);
11541157
let (innermost_ret_ty, self_param) = {
11551158
let find_ret_ty = |it: SyntaxNode| {
11561159
if let Some(item) = ast::Item::cast(it.clone()) {
@@ -1220,6 +1223,7 @@ fn classify_name_ref(
12201223
after_if_expr,
12211224
in_condition,
12221225
ref_expr_parent,
1226+
after_amp,
12231227
is_func_update,
12241228
innermost_ret_ty,
12251229
self_param,

Diff for: crates/ide-completion/src/tests/expression.rs

+109
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ fn baz() {
6666
kw loop
6767
kw match
6868
kw mut
69+
kw raw
6970
kw return
7071
kw self::
7172
kw true
@@ -436,6 +437,114 @@ fn completes_in_let_initializer() {
436437
)
437438
}
438439

440+
#[test]
441+
fn completes_after_ref_expr() {
442+
check(
443+
r#"fn main() { let _ = &$0 }"#,
444+
expect![[r#"
445+
fn main() fn()
446+
bt u32 u32
447+
kw crate::
448+
kw false
449+
kw for
450+
kw if
451+
kw if let
452+
kw loop
453+
kw match
454+
kw mut
455+
kw raw
456+
kw return
457+
kw self::
458+
kw true
459+
kw unsafe
460+
kw while
461+
kw while let
462+
"#]],
463+
);
464+
check(
465+
r#"fn main() { let _ = &raw $0 }"#,
466+
expect![[r#"
467+
fn main() fn()
468+
bt u32 u32
469+
kw const
470+
kw crate::
471+
kw false
472+
kw for
473+
kw if
474+
kw if let
475+
kw loop
476+
kw match
477+
kw mut
478+
kw return
479+
kw self::
480+
kw true
481+
kw unsafe
482+
kw while
483+
kw while let
484+
"#]],
485+
);
486+
check(
487+
r#"fn main() { let _ = &raw const $0 }"#,
488+
expect![[r#"
489+
fn main() fn()
490+
bt u32 u32
491+
kw crate::
492+
kw false
493+
kw for
494+
kw if
495+
kw if let
496+
kw loop
497+
kw match
498+
kw return
499+
kw self::
500+
kw true
501+
kw unsafe
502+
kw while
503+
kw while let
504+
"#]],
505+
);
506+
check(
507+
r#"fn main() { let _ = &raw mut $0 }"#,
508+
expect![[r#"
509+
fn main() fn()
510+
bt u32 u32
511+
kw crate::
512+
kw false
513+
kw for
514+
kw if
515+
kw if let
516+
kw loop
517+
kw match
518+
kw return
519+
kw self::
520+
kw true
521+
kw unsafe
522+
kw while
523+
kw while let
524+
"#]],
525+
);
526+
check(
527+
r#"fn main() { let _ = &mut $0 }"#,
528+
expect![[r#"
529+
fn main() fn()
530+
bt u32 u32
531+
kw crate::
532+
kw false
533+
kw for
534+
kw if
535+
kw if let
536+
kw loop
537+
kw match
538+
kw return
539+
kw self::
540+
kw true
541+
kw unsafe
542+
kw while
543+
kw while let
544+
"#]],
545+
)
546+
}
547+
439548
#[test]
440549
fn struct_initializer_field_expr() {
441550
check(

Diff for: crates/parser/src/grammar/expressions.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,20 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik
339339
// // raw reference operator
340340
// let _ = &raw mut foo;
341341
// let _ = &raw const foo;
342+
// let _ = &raw foo;
342343
// }
343344
T![&] => {
344345
m = p.start();
345346
p.bump(T![&]);
346-
if p.at_contextual_kw(T![raw]) && [T![mut], T![const]].contains(&p.nth(1)) {
347-
p.bump_remap(T![raw]);
348-
p.bump_any();
347+
if p.at_contextual_kw(T![raw]) {
348+
if [T![mut], T![const]].contains(&p.nth(1)) {
349+
p.bump_remap(T![raw]);
350+
p.bump_any();
351+
} else if p.nth_at(1, SyntaxKind::IDENT) {
352+
// we treat raw as keyword in this case
353+
// &raw foo;
354+
p.bump_remap(T![raw]);
355+
}
349356
} else {
350357
p.eat(T![mut]);
351358
}

Diff for: crates/parser/test_data/parser/inline/ok/ref_expr.rast

+19
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,25 @@ SOURCE_FILE
134134
NAME_REF
135135
IDENT "foo"
136136
SEMICOLON ";"
137+
WHITESPACE "\n "
138+
LET_STMT
139+
LET_KW "let"
140+
WHITESPACE " "
141+
WILDCARD_PAT
142+
UNDERSCORE "_"
143+
WHITESPACE " "
144+
EQ "="
145+
WHITESPACE " "
146+
REF_EXPR
147+
AMP "&"
148+
RAW_KW "raw"
149+
WHITESPACE " "
150+
PATH_EXPR
151+
PATH
152+
PATH_SEGMENT
153+
NAME_REF
154+
IDENT "foo"
155+
SEMICOLON ";"
137156
WHITESPACE "\n"
138157
R_CURLY "}"
139158
WHITESPACE "\n"

Diff for: crates/parser/test_data/parser/inline/ok/ref_expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ fn foo() {
77
// raw reference operator
88
let _ = &raw mut foo;
99
let _ = &raw const foo;
10+
let _ = &raw foo;
1011
}

0 commit comments

Comments
 (0)