mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #18952 from lh123/add-raw-keyword-complete
feat: complete raw, const keyword
This commit is contained in:
commit
903bc8133c
@ -581,10 +581,7 @@ impl ExprCollector<'_> {
|
|||||||
let mutability = if raw_tok {
|
let mutability = if raw_tok {
|
||||||
if e.mut_token().is_some() {
|
if e.mut_token().is_some() {
|
||||||
Mutability::Mut
|
Mutability::Mut
|
||||||
} else if e.const_token().is_some() {
|
|
||||||
Mutability::Shared
|
|
||||||
} else {
|
} else {
|
||||||
never!("parser only remaps to raw_token() if matching mutability token follows");
|
|
||||||
Mutability::Shared
|
Mutability::Shared
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,6 +62,7 @@ pub(crate) fn complete_expr_path(
|
|||||||
in_condition,
|
in_condition,
|
||||||
incomplete_let,
|
incomplete_let,
|
||||||
ref ref_expr_parent,
|
ref ref_expr_parent,
|
||||||
|
after_amp,
|
||||||
ref is_func_update,
|
ref is_func_update,
|
||||||
ref innermost_ret_ty,
|
ref innermost_ret_ty,
|
||||||
ref impl_,
|
ref impl_,
|
||||||
@ -69,8 +70,23 @@ pub(crate) fn complete_expr_path(
|
|||||||
..
|
..
|
||||||
} = expr_ctx;
|
} = expr_ctx;
|
||||||
|
|
||||||
let wants_mut_token =
|
let (has_raw_token, has_const_token, has_mut_token) = ref_expr_parent
|
||||||
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
|
.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 {
|
let scope_def_applicable = |def| match def {
|
||||||
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false,
|
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false,
|
||||||
@ -354,6 +370,12 @@ pub(crate) fn complete_expr_path(
|
|||||||
add_keyword("else if", "else if $1 {\n $0\n}");
|
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 {
|
if wants_mut_token {
|
||||||
add_keyword("mut", "mut ");
|
add_keyword("mut", "mut ");
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,7 @@ pub(crate) struct PathExprCtx {
|
|||||||
pub(crate) in_condition: bool,
|
pub(crate) in_condition: bool,
|
||||||
pub(crate) incomplete_let: bool,
|
pub(crate) incomplete_let: bool,
|
||||||
pub(crate) ref_expr_parent: Option<ast::RefExpr>,
|
pub(crate) ref_expr_parent: Option<ast::RefExpr>,
|
||||||
|
pub(crate) after_amp: bool,
|
||||||
/// The surrounding RecordExpression we are completing a functional update
|
/// The surrounding RecordExpression we are completing a functional update
|
||||||
pub(crate) is_func_update: Option<ast::RecordExpr>,
|
pub(crate) is_func_update: Option<ast::RecordExpr>,
|
||||||
pub(crate) self_param: Option<hir::SelfParam>,
|
pub(crate) self_param: Option<hir::SelfParam>,
|
||||||
|
@ -1151,6 +1151,9 @@ fn classify_name_ref(
|
|||||||
let after_if_expr = after_if_expr(it.clone());
|
let after_if_expr = after_if_expr(it.clone());
|
||||||
let ref_expr_parent =
|
let ref_expr_parent =
|
||||||
path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
|
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 (innermost_ret_ty, self_param) = {
|
||||||
let find_ret_ty = |it: SyntaxNode| {
|
let find_ret_ty = |it: SyntaxNode| {
|
||||||
if let Some(item) = ast::Item::cast(it.clone()) {
|
if let Some(item) = ast::Item::cast(it.clone()) {
|
||||||
@ -1220,6 +1223,7 @@ fn classify_name_ref(
|
|||||||
after_if_expr,
|
after_if_expr,
|
||||||
in_condition,
|
in_condition,
|
||||||
ref_expr_parent,
|
ref_expr_parent,
|
||||||
|
after_amp,
|
||||||
is_func_update,
|
is_func_update,
|
||||||
innermost_ret_ty,
|
innermost_ret_ty,
|
||||||
self_param,
|
self_param,
|
||||||
|
@ -66,6 +66,7 @@ fn baz() {
|
|||||||
kw loop
|
kw loop
|
||||||
kw match
|
kw match
|
||||||
kw mut
|
kw mut
|
||||||
|
kw raw
|
||||||
kw return
|
kw return
|
||||||
kw self::
|
kw self::
|
||||||
kw true
|
kw true
|
||||||
@ -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]
|
#[test]
|
||||||
fn struct_initializer_field_expr() {
|
fn struct_initializer_field_expr() {
|
||||||
check(
|
check(
|
||||||
|
@ -339,13 +339,20 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik
|
|||||||
// // raw reference operator
|
// // raw reference operator
|
||||||
// let _ = &raw mut foo;
|
// let _ = &raw mut foo;
|
||||||
// let _ = &raw const foo;
|
// let _ = &raw const foo;
|
||||||
|
// let _ = &raw foo;
|
||||||
// }
|
// }
|
||||||
T![&] => {
|
T![&] => {
|
||||||
m = p.start();
|
m = p.start();
|
||||||
p.bump(T![&]);
|
p.bump(T![&]);
|
||||||
if p.at_contextual_kw(T![raw]) && [T![mut], T![const]].contains(&p.nth(1)) {
|
if p.at_contextual_kw(T![raw]) {
|
||||||
p.bump_remap(T![raw]);
|
if [T![mut], T![const]].contains(&p.nth(1)) {
|
||||||
p.bump_any();
|
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 {
|
} else {
|
||||||
p.eat(T![mut]);
|
p.eat(T![mut]);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,25 @@ SOURCE_FILE
|
|||||||
NAME_REF
|
NAME_REF
|
||||||
IDENT "foo"
|
IDENT "foo"
|
||||||
SEMICOLON ";"
|
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"
|
WHITESPACE "\n"
|
||||||
R_CURLY "}"
|
R_CURLY "}"
|
||||||
WHITESPACE "\n"
|
WHITESPACE "\n"
|
||||||
|
@ -7,4 +7,5 @@ fn foo() {
|
|||||||
// raw reference operator
|
// raw reference operator
|
||||||
let _ = &raw mut foo;
|
let _ = &raw mut foo;
|
||||||
let _ = &raw const foo;
|
let _ = &raw const foo;
|
||||||
|
let _ = &raw foo;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user