macro_rules! threadsafe_function {
    (
        $module_name:ident ($js_parent_name:literal: $js_parent_type:ty){
            $(
                $function_js_name:literal: $function_module_name:ident(
                    $(
                        $argument_type:ty
                    ),+
                ) -> $return_type:ty;
            )*
        }
    ) => {
        pub mod $module_name {
            $(
                pub mod $function_module_name {
                    use napi::bindgen_prelude::JsObjectValue;

                    pub type Arguments = napi::bindgen_prelude::FnArgs<($($argument_type,)*)>;
                    pub type Return = $return_type;

                    pub type Prototype = napi::threadsafe_function::ThreadsafeFunction<
                        Arguments,
                        Return,
                        Arguments,
                        napi::Status,
                        false,
                        false,
                        0,
                    >;

                    pub fn get(vscode_object: &napi::bindgen_prelude::Object) -> Result<Prototype, napi::Error> {
                        let parent: $js_parent_type = vscode_object.get_named_property($js_parent_name)?;

                        parent.get_named_property($function_js_name)
                    }
                }
            )*
        }
    };
}

pub(crate) use threadsafe_function;