Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: complete raw, const keyword #18952

Merged
merged 2 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
Loading