about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlh123 <1585086582@qq.com>2025-01-16 18:05:30 +0800
committerlh123 <1585086582@qq.com>2025-01-16 18:27:59 +0800
commit341a6d5bbaae3c032a7db1b3a512d4537daa87ee (patch)
tree179290ea6e7ae889a5a0a659fd6c6a342f61dbb5
parent88ae0896f9e8bea458428c5edfd1068c27bcd2a2 (diff)
downloadrust-341a6d5bbaae3c032a7db1b3a512d4537daa87ee.tar.gz
rust-341a6d5bbaae3c032a7db1b3a512d4537daa87ee.zip
feat: complete raw, const keyword
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs89
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs13
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast19
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs1
6 files changed, 144 insertions, 8 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index d7e28da644a..1327bb3ab59 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -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 {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index c2e5eefe101..49a96e27e70 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -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 ");
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index d0dc6206f4d..69378747340 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -66,6 +66,7 @@ fn baz() {
             kw loop
             kw match
             kw mut
+            kw raw
             kw return
             kw self::
             kw true
@@ -437,6 +438,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(
         r#"
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 3b3f11be130..03439b784d3 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -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]);
             }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast
index 108b0802c33..8dc916e5cc5 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast
@@ -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"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs
index c5262f4469b..31a2485b439 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs
@@ -7,4 +7,5 @@ fn foo() {
     // raw reference operator
     let _ = &raw mut foo;
     let _ = &raw const foo;
+    let _ = &raw foo;
 }