diff options
Diffstat (limited to 'syntax/qualified.rs')
-rw-r--r-- | syntax/qualified.rs | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/syntax/qualified.rs b/syntax/qualified.rs index 96f07c19..5f182fa9 100644 --- a/syntax/qualified.rs +++ b/syntax/qualified.rs @@ -1,5 +1,5 @@ use syn::ext::IdentExt; -use syn::parse::{ParseStream, Result}; +use syn::parse::{Error, ParseStream, Result}; use syn::{Ident, LitStr, Token}; pub struct QualifiedName { @@ -8,21 +8,8 @@ pub struct QualifiedName { impl QualifiedName { pub fn parse_unquoted(input: ParseStream) -> Result<Self> { - let mut segments = Vec::new(); - let mut trailing_punct = true; - let leading_colons: Option<Token![::]> = input.parse()?; - while trailing_punct && input.peek(Ident::peek_any) { - let ident = Ident::parse_any(input)?; - segments.push(ident); - let colons: Option<Token![::]> = input.parse()?; - trailing_punct = colons.is_some(); - } - if segments.is_empty() && leading_colons.is_none() { - return Err(input.error("expected path")); - } else if trailing_punct { - return Err(input.error("expected path segment")); - } - Ok(QualifiedName { segments }) + let allow_raw = true; + parse_unquoted(input, allow_raw) } pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> { @@ -32,10 +19,41 @@ impl QualifiedName { let segments = Vec::new(); Ok(QualifiedName { segments }) } else { - lit.parse_with(Self::parse_unquoted) + lit.parse_with(|input: ParseStream| { + let allow_raw = false; + parse_unquoted(input, allow_raw) + }) } } else { Self::parse_unquoted(input) } } } + +fn parse_unquoted(input: ParseStream, allow_raw: bool) -> Result<QualifiedName> { + let mut segments = Vec::new(); + let mut trailing_punct = true; + let leading_colons: Option<Token![::]> = input.parse()?; + while trailing_punct && input.peek(Ident::peek_any) { + let mut ident = Ident::parse_any(input)?; + if let Some(unraw) = ident.to_string().strip_prefix("r#") { + if !allow_raw { + let msg = format!( + "raw identifier `{}` is not allowed in a quoted namespace; use `{}`, or remove quotes", + ident, unraw, + ); + return Err(Error::new(ident.span(), msg)); + } + ident = Ident::new(unraw, ident.span()); + } + segments.push(ident); + let colons: Option<Token![::]> = input.parse()?; + trailing_punct = colons.is_some(); + } + if segments.is_empty() && leading_colons.is_none() { + return Err(input.error("expected path")); + } else if trailing_punct { + return Err(input.error("expected path segment")); + } + Ok(QualifiedName { segments }) +} |