You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: assign_property.rs
    path of file: ./repos/Relm4/relm4-macros/src/widgets/parse
    
    the code of the file until where you have to start completion: use proc_macro2::TokenStream as TokenStream2;
use quote::{quote_spanned, ToTokens};
use syn::parse::ParseStream;
use syn::spanned::Spanned;
use syn::{Error, Expr, ExprCall, ExprField, Ident, Member, Result, Token};

use crate::args::Args;
use crate::widgets::parse_util::attr_twice_error;
use crate::widgets::{AssignProperty, AssignPropertyAttr, Attr, Attrs};

struct ProcessedAttrs {
    watch: AssignPropertyAttr,
    iterative: bool,
    block_signals: Vec<Ident>,
    chain: Option<Box<Expr>>,
}

impl AssignProperty {
    pub(super) fn parse(
        input: ParseStream<'_>,
        attributes: Option<Attrs>,
        args: Option<Args<Expr>>,
    ) -> Result<Self> {
        let optional_assign = input.parse::<Token![?]>().is_ok();
        let colon: Token! [:] = input.parse()?;
        let colon_span = colon.span();

        let expr = match input.parse() {
            Ok(expr) => expr,
            Err(parse_err) => {
                let mut err = Error::new(colon_span, "Did you confuse `=` with`:`?");
                err.combine(parse_err);
                return Err(err);
            }
        };

        let ProcessedAttrs {
            watch,
            iterative,
            block_signals,
            chain,
        } = Self::process_attributes(&expr, attributes)?;

        Ok(Self {
            attr: watch,
            expr,
            args,
            optional_assign,
            iterative,
            block_signals,
            chain,
        })
    }

    fn process_attributes(assign_expr: &Expr, attrs: Option<Attrs>) -> Result<ProcessedAttrs> {
        if let Some(attrs) = attrs {
            let mut iterative = false;
            let mut watch = AssignPropertyAttr::None;
            let mut block_signals = Vec::with_capacity(0);
            let mut chain = None;

            for attr in attrs.inner {
                let span = attr.span();
                match attr {
                    Attr::Iterate(_) => {
                        if iterative {
                            return Err(attr_twice_error(span));
                        }
                        iterative = true;
                    }
                    Attr::Watch(_, skip_init) => {
                        if watch == AssignPropertyAttr::None {
                            watch = AssignPropertyAttr::Watch { skip_init }
                        } else {
                            return Err(attr_twice_error(span));
                        }
                    }
                    Attr::Track(_, skip_init, expr) => {
                        if watch == AssignPropertyAttr::None {
                            watch = if let Some(expr) = expr {
                                AssignPropertyAttr::Track {
                                    track_expr: expr.to_token_stream(),
                              
    
    fn process_attributes(assign_expr: &Expr, attrs: Option<Attrs>) -> Result<ProcessedAttrs> {
        if let Some(attrs) = attrs {
            let mut iterative = false;
            let mut watch = AssignPropertyAttr::None;
            let mut block_signals = Vec::with_capacity(0);
            let mut chain = None;

            for attr in attrs.inner {
                let span = attr.span();
                match attr {
                    Attr::Iterate(_) => {
                        if iterative {
                            return Err(attr_twice_error(span));
                        }
                        iterative = true;
                    }
                    Attr::Watch(_, skip_init) => {
                        if watch == AssignPropertyAttr::None {
                            watch = AssignPropertyAttr::Watch { skip_init }
                        } else {
                            return Err(attr_twice_error(span));
                        }
                    }
                    Attr::Track(_, skip_init, expr) => {
                        if watch == AssignPropertyAttr::None {
                            watch = if let Some(expr) = expr {
                                AssignPropertyAttr::Track {
                                    track_expr: expr.to_token_stream(),
                                    skip_init,
                                    paste_model: false,
                                }
                            } else {
                                AssignPropertyAttr::Track {
                                    track_expr: generate_tracker_from_expression(assign_expr)?,
                                    skip_init,
                                    paste_model: true,
                                }
                            };
                        } else {
                            return Err(attr_twice_error(span));
                        }
                    }
                    Attr::BlockSignal(_, idents) => {
                        if block_signals.is_empty() {
                            block_signals = idents;
                        } else {
                            return Err(attr_twice_error(span));
                        }
                    }
                    Attr::Chain(_, expr) => {
                        if chain.is_none() {
                            chain = Some(expr);
                        } else {
                            return Err(attr_twice_error(span));
                        }
                    }
                    _ => {
                        return Err(Error::new(
                            attr.span(),
                            "Properties can only have `watch`, `track` or `iterative` as attribute.",
                        ));
                    }
                }
            }
            Ok(ProcessedAttrs {
                watch,
                iterative,
                block_signals,
                chain,
            })
        } else {
            Ok(ProcessedAttrs {
                watch: AssignPropertyAttr::None,
                iterative: false,
                block_signals: Vec::with_capacity(0),
                chain: None,
            })
        }
    }