Skip to content

Commit

Permalink
Merge pull request #18952 from lh123/add-raw-keyword-complete
Browse files Browse the repository at this point in the history
feat: complete raw, const keyword
  • Loading branch information
Veykril authored Jan 16, 2025
2 parents 1f717b0 + a282733 commit 903bc81
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 8 deletions.
3 changes: 0 additions & 3 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
26 changes: 24 additions & 2 deletions crates/ide-completion/src/completions/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,31 @@ pub(crate) fn complete_expr_path(
in_condition,
incomplete_let,
ref ref_expr_parent,
after_amp,
ref is_func_update,
ref innermost_ret_ty,
ref impl_,
in_match_guard,
..
} = 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, has_const_token, has_mut_token) = ref_expr_parent
.as_ref()
.map(|it| (it.raw_token().is_some(), it.const_token().is_some(), it.mut_token().is_some()))
.unwrap_or((false, false, false));

let wants_raw_token = ref_expr_parent.is_some() && !has_raw_token && after_amp;
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,
Expand Down Expand Up @@ -354,6 +370,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 ");
}
Expand Down
1 change: 1 addition & 0 deletions crates/ide-completion/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ pub(crate) struct PathExprCtx {
pub(crate) in_condition: bool,
pub(crate) incomplete_let: bool,
pub(crate) ref_expr_parent: Option<ast::RefExpr>,
pub(crate) after_amp: bool,
/// The surrounding RecordExpression we are completing a functional update
pub(crate) is_func_update: Option<ast::RecordExpr>,
pub(crate) self_param: Option<hir::SelfParam>,
Expand Down
4 changes: 4 additions & 0 deletions crates/ide-completion/src/context/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,9 @@ fn classify_name_ref(
let after_if_expr = after_if_expr(it.clone());
let ref_expr_parent =
path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
let after_amp = non_trivia_sibling(it.clone().into(), Direction::Prev)
.map(|it| it.kind() == SyntaxKind::AMP)
.unwrap_or(false);
let (innermost_ret_ty, self_param) = {
let find_ret_ty = |it: SyntaxNode| {
if let Some(item) = ast::Item::cast(it.clone()) {
Expand Down Expand Up @@ -1220,6 +1223,7 @@ fn classify_name_ref(
after_if_expr,
in_condition,
ref_expr_parent,
after_amp,
is_func_update,
innermost_ret_ty,
self_param,
Expand Down
109 changes: 109 additions & 0 deletions crates/ide-completion/src/tests/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ fn baz() {
kw loop
kw match
kw mut
kw raw
kw return
kw self::
kw true
Expand Down Expand Up @@ -436,6 +437,114 @@ 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
"#]],
);
check(
r#"fn main() { let _ = &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(
Expand Down
13 changes: 10 additions & 3 deletions crates/parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
Expand Down
19 changes: 19 additions & 0 deletions crates/parser/test_data/parser/inline/ok/ref_expr.rast
Original file line number Diff line number Diff line change
Expand Up @@ -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"
1 change: 1 addition & 0 deletions crates/parser/test_data/parser/inline/ok/ref_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ fn foo() {
// raw reference operator
let _ = &raw mut foo;
let _ = &raw const foo;
let _ = &raw foo;
}

0 comments on commit 903bc81

Please sign in to comment.