Handle raw identifiers in proc macro server

This commit is contained in:
Ryo Yoshida 2022-12-03 22:57:08 +09:00
parent 04a2ac2de2
commit de591f08d6
No known key found for this signature in database
GPG key ID: E25698A930586171
5 changed files with 27 additions and 12 deletions

View file

@ -471,8 +471,12 @@ impl server::Punct for RustAnalyzer {
} }
impl server::Ident for RustAnalyzer { impl server::Ident for RustAnalyzer {
fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident { 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 }))) 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 { fn span(&mut self, ident: Self::Ident) -> Self::Span {

View file

@ -486,8 +486,12 @@ impl server::Punct for RustAnalyzer {
} }
impl server::Ident for RustAnalyzer { impl server::Ident for RustAnalyzer {
fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident { 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 }))) 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 { fn span(&mut self, ident: Self::Ident) -> Self::Span {

View file

@ -107,8 +107,8 @@ impl server::TokenStream for RustAnalyzer {
} }
bridge::TokenTree::Ident(ident) => { bridge::TokenTree::Ident(ident) => {
// FIXME: handle raw idents
let text = ident.sym.text(); 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 ident: tt::Ident = tt::Ident { text, id: ident.span };
let leaf = tt::Leaf::from(ident); let leaf = tt::Leaf::from(ident);
let tree = TokenTree::from(leaf); let tree = TokenTree::from(leaf);
@ -182,9 +182,8 @@ impl server::TokenStream for RustAnalyzer {
.map(|tree| match tree { .map(|tree| match tree {
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
bridge::TokenTree::Ident(bridge::Ident { bridge::TokenTree::Ident(bridge::Ident {
sym: Symbol::intern(&ident.text), sym: Symbol::intern(&ident.text.trim_start_matches("r#")),
// FIXME: handle raw idents is_raw: ident.text.starts_with("r#"),
is_raw: false,
span: ident.id, span: ident.id,
}) })
} }

View file

@ -63,7 +63,7 @@ fn test_fn_like_macro_clone_raw_ident() {
"r#async", "r#async",
expect![[r#" expect![[r#"
SUBTREE $ SUBTREE $
IDENT async 4294967295"#]], IDENT r#async 4294967295"#]],
); );
} }
@ -86,15 +86,13 @@ fn test_fn_like_mk_literals() {
#[test] #[test]
fn test_fn_like_mk_idents() { 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( assert_expand(
"fn_like_mk_idents", "fn_like_mk_idents",
r#""#, r#""#,
expect![[r#" expect![[r#"
SUBTREE $ SUBTREE $
IDENT standard 4294967295 IDENT standard 4294967295
IDENT raw 4294967295"#]], IDENT r#raw 4294967295"#]],
); );
} }

View file

@ -86,10 +86,20 @@ pub enum Spacing {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Ident { pub struct Ident {
/// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
pub text: SmolStr, pub text: SmolStr,
pub id: TokenId, 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 { impl Leaf {
pub fn id(&self) -> TokenId { pub fn id(&self) -> TokenId {
match self { match self {