xso-proc: fix renaming attributes using a static item

Jonas Schäfer created

This was broken by d4d520e by accident, and of course we didn't have
tests for that :-).

(we do, now)

Change summary

parsers/src/util/macro_tests.rs | 18 ++++++++++--------
xso-proc/src/meta.rs            | 33 +++++++++++++++++----------------
2 files changed, 27 insertions(+), 24 deletions(-)

Detailed changes

parsers/src/util/macro_tests.rs 🔗

@@ -66,6 +66,13 @@ type Result = ((),);
 
 static NS1: &str = "urn:example:ns1";
 
+static SOME_NAME: &::xso::exports::rxml::strings::NcNameStr = {
+    #[allow(unsafe_code)]
+    unsafe {
+        ::xso::exports::rxml::strings::NcNameStr::from_str_unchecked("bar")
+    }
+};
+
 #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
 #[xml(namespace = NS1, name = "foo")]
 struct Empty;
@@ -149,13 +156,6 @@ fn empty_qname_check_has_precedence_over_attr_check() {
     }
 }
 
-static SOME_NAME: &::xso::exports::rxml::strings::NcNameStr = {
-    #[allow(unsafe_code)]
-    unsafe {
-        ::xso::exports::rxml::strings::NcNameStr::from_str_unchecked("bar")
-    }
-};
-
 #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
 #[xml(namespace = NS1, name = SOME_NAME)]
 struct NamePath;
@@ -234,6 +234,8 @@ fn required_attribute_missing() {
 struct RenamedAttribute {
     #[xml(attribute = "a1")]
     foo: String,
+    #[xml(attribute = SOME_NAME)]
+    bar: String,
 }
 
 #[test]
@@ -243,7 +245,7 @@ fn renamed_attribute_roundtrip() {
         option::Option::{None, Some},
         result::Result::{Err, Ok},
     };
-    roundtrip_full::<RenamedAttribute>("<attr xmlns='urn:example:ns1' a1='bar'/>");
+    roundtrip_full::<RenamedAttribute>("<attr xmlns='urn:example:ns1' a1='bar' bar='baz'/>");
 }
 
 #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]

xso-proc/src/meta.rs 🔗

@@ -207,6 +207,12 @@ impl XmlCompoundMeta {
 fn parse_prefixed_name(
     value: syn::parse::ParseStream<'_>,
 ) -> Result<(Option<NamespaceRef>, NameRef)> {
+    if !value.peek(LitStr) {
+        // if we don't have a string literal next, we delegate to the default
+        // `NameRef` parser.
+        return Ok((None, value.parse()?));
+    }
+
     let name: LitStr = value.parse()?;
     let name_span = name.span();
     let (prefix, name) = match name
@@ -284,23 +290,18 @@ impl XmlFieldMeta {
                         return Err(Error::new_spanned(meta.path, "duplicate `name` key"));
                     }
                     let value = meta.value()?;
-                    name = if value.peek(LitStr) {
-                        let name_span = value.span();
-                        let (new_namespace, name) = parse_prefixed_name(value)?;
-                        if let Some(new_namespace) = new_namespace {
-                            if namespace.is_some() {
-                                return Err(Error::new(
-                                    name_span,
-                                    "cannot combine `namespace` key with prefixed `name`",
-                                ));
-                            }
-                            namespace = Some(new_namespace);
+                    let name_span = value.span();
+                    let (new_namespace, new_name) = parse_prefixed_name(value)?;
+                    if let Some(new_namespace) = new_namespace {
+                        if namespace.is_some() {
+                            return Err(Error::new(
+                                name_span,
+                                "cannot combine `namespace` key with prefixed `name`",
+                            ));
                         }
-                        Some(name)
-                    } else {
-                        // just use the normal parser
-                        Some(value.parse()?)
-                    };
+                        namespace = Some(new_namespace);
+                    }
+                    name = Some(new_name);
                     Ok(())
                 } else if meta.path.is_ident("namespace") {
                     if namespace.is_some() {