Repository: serde-rs/serde
File: serde_codegen/src/attr.rs (Rust)

Code before:

impl ContainerAttrs {
    /// Extract out the `#[serde(...)]` attributes from an item.
    pub fn from_item(cx: &ExtCtxt, item: &ast::Item) -> Result<Self, Error> {
        let mut container_attrs = ContainerAttrs {
            name: Name::new(item.ident),
            deny_unknown_fields: false,
            ser_bound: None,
            de_bound: None,
        };

        for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) {
            for meta_item in meta_items {
                match meta_item.node {
                    // Parse `#[serde(rename="foo")]`
                    ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
                        let s = try!(get_str_from_lit(cx, name, lit));

                        container_attrs.name.serialize_name = Some(s.clone());
                        container_attrs.name.deserialize_name = Some(s);
                    }

                    // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
                    ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
                        let (ser_name, de_name) = try!(get_renames(cx, meta_items));

                        container_attrs.name.serialize_name = ser_name;
                        container_attrs.name.deserialize_name = de_name;
                    }

                    // Parse `#[serde(deny_unknown_fields)]`
                    ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
                        container_attrs.deny_unknown_fields = true;
                    }

                    // Parse `#[serde(bound="D: Serialize")]`
                    ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
                        let where_predicates = try!(parse_lit_into_where(cx, name, lit));
                        container_attrs.ser_bound = Some(where_predicates.clone());
                        container_attrs.de_bound = Some(where_predicates);
                    }

                    // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
                    ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
                        let (ser_bound, de_bound) = try!(get_where_predicates(cx, meta_items));
                        container_attrs.ser_bound = ser_bound;
                        container_attrs.de_bound = de_bound;
                    }

                    _ => {
                        cx.span_err(

Review comment (suggestion):
I think this should also check whether this is overwriting a previous value and emit an error (or at least a warning) if it is.


Code after:

impl ContainerAttrs {
    /// Extract out the `#[serde(...)]` attributes from an item.
    pub fn from_item(cx: &ExtCtxt, item: &ast::Item) -> Result<Self, Error> {
        let mut container_attrs = ContainerAttrs {
            name: Name::new(item.ident),
            deny_unknown_fields: false,
            ser_bound: None,
            de_bound: None,
        };

        for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) {
            for meta_item in meta_items {
                match meta_item.node {
                    // Parse `#[serde(rename="foo")]`
                    ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => {
                        let s = try!(get_str_from_lit(cx, name, lit));
                        container_attrs.name.serialize_name = Some(s.clone());
                        container_attrs.name.deserialize_name = Some(s);
                    }

                    // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
                    ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => {
                        let (ser_name, de_name) = try!(get_renames(cx, meta_items));
                        if ser_name.is_some() {
                            container_attrs.name.serialize_name = ser_name;
                        }
                        if de_name.is_some() {
                            container_attrs.name.deserialize_name = de_name;
                        }
                    }

                    // Parse `#[serde(deny_unknown_fields)]`
                    ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => {
                        container_attrs.deny_unknown_fields = true;
                    }

                    // Parse `#[serde(bound="D: Serialize")]`
                    ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
                        let where_predicates = try!(parse_lit_into_where(cx, name, lit));
                        container_attrs.ser_bound = Some(where_predicates.clone());
                        container_attrs.de_bound = Some(where_predicates);
                    }

                    // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
                    ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
                        let (ser_bound, de_bound) = try!(get_where_predicates(cx, meta_items));
                        if ser_bound.is_some() {
                            container_attrs.ser_bound = ser_bound;
                        }
                        if de_bound.is_some() {