about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-12-03 18:42:33 +0000
committerbors <bors@rust-lang.org>2022-12-03 18:42:33 +0000
commit957b4bb2164e57a58d7e6cb5b4915b298dab9391 (patch)
treee14d3c1d2454393507c6e821a16906455e9ac6b6
parent04a2ac2de20565e87c561bdb3c3814dfeec1513c (diff)
parentde591f08d6a38f1b70365622f62352583c9c06ef (diff)
downloadrust-957b4bb2164e57a58d7e6cb5b4915b298dab9391.tar.gz
rust-957b4bb2164e57a58d7e6cb5b4915b298dab9391.zip
Auto merge of #13717 - lowr:fix/proc-macro-ident-is-raw, r=Veykril
Handle raw identifiers in proc macro server

Fixes #13706

When proc macros create `proc_macro::Ident`s, they pass an identifier text without "r#" prefix and a flag `is_raw` to proc macro server. Our `tt::Ident` currently stores the text *with* "r#" so we need to adjust them somewhere.

Rather than following rustc and adding `is_raw` field to our `tt::Ident`, I opted for adjusting the representation of identifiers in proc macro server, because we don't need the field outside it.

It's hard to write regression test for this, but at least I:
- ran `cargo +nightly t --features sysroot-abi` and all the tests passed
- built proc macro server with `cargo +nightly b -r --bin rust-analyzer-proc-macro-srv --features sysroot-abi` and made sure #13706 resolved
  - For the record, the nightly versions used are `rustc 1.67.0-nightly (32e613bba 2022-12-02)` and `cargo 1.67.0-nightly (e027c4b5d 2022-11-25)`.
-rw-r--r--crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs8
-rw-r--r--crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs8
-rw-r--r--crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs7
-rw-r--r--crates/proc-macro-srv/src/tests/mod.rs6
-rw-r--r--crates/tt/src/lib.rs10
5 files changed, 27 insertions, 12 deletions
diff --git a/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs b/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs
index b1e982f4779..c19684850fc 100644
--- a/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs
+++ b/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs
@@ -471,8 +471,12 @@ impl server::Punct for RustAnalyzer {
 }
 
 impl server::Ident for RustAnalyzer {
-    fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident {
-        IdentId(self.ident_interner.intern(&IdentData(tt::Ident { text: string.into(), id: span })))
+    fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
+        IdentId(self.ident_interner.intern(&IdentData(tt::Ident::new_with_is_raw(
+            string.into(),
+            span,
+            is_raw,
+        ))))
     }
 
     fn span(&mut self, ident: Self::Ident) -> Self::Span {
diff --git a/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs b/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs
index ed49cc75966..eb9d7a94b5d 100644
--- a/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs
+++ b/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs
@@ -486,8 +486,12 @@ impl server::Punct for RustAnalyzer {
 }
 
 impl server::Ident for RustAnalyzer {
-    fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident {
-        IdentId(self.ident_interner.intern(&IdentData(tt::Ident { text: string.into(), id: span })))
+    fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
+        IdentId(self.ident_interner.intern(&IdentData(tt::Ident::new_with_is_raw(
+            string.into(),
+            span,
+            is_raw,
+        ))))
     }
 
     fn span(&mut self, ident: Self::Ident) -> Self::Span {
diff --git a/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs b/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
index e4e43e97dde..d38bd9400b5 100644
--- a/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
+++ b/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
@@ -107,8 +107,8 @@ impl server::TokenStream for RustAnalyzer {
             }
 
             bridge::TokenTree::Ident(ident) => {
-                // FIXME: handle raw idents
                 let text = ident.sym.text();
+                let text = if ident.is_raw { tt::SmolStr::from_iter(["r#", &text]) } else { text };
                 let ident: tt::Ident = tt::Ident { text, id: ident.span };
                 let leaf = tt::Leaf::from(ident);
                 let tree = TokenTree::from(leaf);
@@ -182,9 +182,8 @@ impl server::TokenStream for RustAnalyzer {
             .map(|tree| match tree {
                 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
                     bridge::TokenTree::Ident(bridge::Ident {
-                        sym: Symbol::intern(&ident.text),
-                        // FIXME: handle raw idents
-                        is_raw: false,
+                        sym: Symbol::intern(&ident.text.trim_start_matches("r#")),
+                        is_raw: ident.text.starts_with("r#"),
                         span: ident.id,
                     })
                 }
diff --git a/crates/proc-macro-srv/src/tests/mod.rs b/crates/proc-macro-srv/src/tests/mod.rs
index cc0fc91fe98..1ccc170f422 100644
--- a/crates/proc-macro-srv/src/tests/mod.rs
+++ b/crates/proc-macro-srv/src/tests/mod.rs
@@ -63,7 +63,7 @@ fn test_fn_like_macro_clone_raw_ident() {
         "r#async",
         expect![[r#"
             SUBTREE $
-              IDENT   async 4294967295"#]],
+              IDENT   r#async 4294967295"#]],
     );
 }
 
@@ -86,15 +86,13 @@ fn test_fn_like_mk_literals() {
 
 #[test]
 fn test_fn_like_mk_idents() {
-    // FIXME: this test is wrong: raw should be 'r#raw' but ABIs 1.64 and below
-    // simply ignore `is_raw` when implementing the `Ident` interface.
     assert_expand(
         "fn_like_mk_idents",
         r#""#,
         expect![[r#"
             SUBTREE $
               IDENT   standard 4294967295
-              IDENT   raw 4294967295"#]],
+              IDENT   r#raw 4294967295"#]],
     );
 }
 
diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs
index a54861de958..85daec262c4 100644
--- a/crates/tt/src/lib.rs
+++ b/crates/tt/src/lib.rs
@@ -86,10 +86,20 @@ pub enum Spacing {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Ident {
+    /// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
     pub text: SmolStr,
     pub id: TokenId,
 }
 
+impl Ident {
+    /// Constructor intended to be used only by proc macro server. `text` should not contain raw
+    /// identifier prefix.
+    pub fn new_with_is_raw(text: SmolStr, id: TokenId, is_raw: bool) -> Self {
+        let text = if is_raw { SmolStr::from_iter(["r#", &text]) } else { text };
+        Ident { text, id }
+    }
+}
+
 impl Leaf {
     pub fn id(&self) -> TokenId {
         match self {