Refactor event handling to support both namespaces and objects

finchie
Dec 15, 2025, 1:02 PM
YKBMKWDPOQKACONKDMURG76BE7N7DA4HLM57V7ARYZPQOHDFCE5QC

Dependencies

  • [2] WFWTKCJN Create initial Visual Studio Code extension
  • [3] 6AUGQLIK Add basic panic handling

Change contents

  • replacement in extensions/vscode/src/vscode_sys/workspace.rs at line 4
    [2.54485][2.54485:54584]()
    use super::macros::{event_handler, namespace_field_getter, namespace_function, register_provider};
    [2.54485]
    [2.54584]
    use super::macros::{
    namespace_event_handler, namespace_field_getter, namespace_function, register_provider,
    };
  • replacement in extensions/vscode/src/vscode_sys/workspace.rs at line 12
    [2.54728][2.54728:54988]()
    event_handler!(
    "workspace",
    "onDidChangeTextDocument",
    on_did_change_text_document(TextDocumentChangeEvent)
    );
    event_handler!(
    "workspace",
    "onDidChangeWorkspaceFolders",
    on_did_change_workspace_folders(WorkspaceFoldersChangeEvent)
    );
    [2.54728]
    [2.54988]
    namespace_event_handler! {
    "workspace" {
    "onDidChangeTextDocument": on_did_change_text_document(TextDocumentChangeEvent);
    "onDidChangeWorkspaceFolders": on_did_change_workspace_folders(WorkspaceFoldersChangeEvent);
    }
    }
  • replacement in extensions/vscode/src/vscode_sys/window.rs at line 4
    [2.55675][2.55675:55774]()
    use super::macros::{event_handler, namespace_field_getter, namespace_function, register_provider};
    [2.55675]
    [2.55774]
    use super::macros::{
    namespace_event_handler, namespace_field_getter, namespace_function, register_provider,
    };
  • replacement in extensions/vscode/src/vscode_sys/window.rs at line 12
    [2.55918][2.55918:56188]()
    event_handler!(
    "window",
    "onDidChangeTextEditorSelection",
    on_did_change_text_editor_selections(TextEditorSelectionChangeEvent)
    );
    event_handler!(
    "window",
    "onDidChangeVisibleTextEditors",
    on_did_change_visible_text_editors(Vec<TextEditor>)
    );
    [2.55918]
    [2.56188]
    namespace_event_handler! {
    "window" {
    "onDidChangeTextEditorSelection": on_did_change_text_editor_selections(TextEditorSelectionChangeEvent);
    "onDidChangeVisibleTextEditors": on_did_change_visible_text_editors(Vec<TextEditor>);
    }
    }
  • edit in extensions/vscode/src/vscode_sys/macros/object/mod.rs at line 1
    [2.69646]
    [2.69647]
    pub mod event_handler;
  • file addition: event_handler.rs (----------)
    [2.69613]
    macro_rules! object_event_handler {
    ($interface_name:ident {
    $(
    $function_js_name:literal: $function_rust_name:ident($event_type:ty);
    )*
    }) => {
    impl<'env> $interface_name<'env> {
    $(
    pub fn $function_rust_name<F>(
    &self,
    env: &napi::Env,
    handler: F,
    // TODO: generic errors
    ) -> Result<(), napi::Error>
    where
    F: for<'function_context> Fn(
    &'function_context napi::Env,
    $event_type,
    ) -> Result<(), napi::Error>
    + std::panic::RefUnwindSafe
    + 'static,
    {
    crate::vscode_sys::macros::event_handler_body! {
    env,
    handler,
    self.inner,
    $function_js_name,
    $function_rust_name($event_type)
    }
    }
    )*
    }
    };
    }
    pub(crate) use object_event_handler;
  • edit in extensions/vscode/src/vscode_sys/macros/namespace/mod.rs at line 1
    [2.75360]
    [2.75361]
    pub mod event_handler;
  • file addition: event_handler.rs (----------)
    [2.75327]
    macro_rules! namespace_event_handler {
    ($namespace:literal {
    $(
    $function_js_name:literal: $function_rust_name:ident($event_type:ty);
    )*
    }) => {
    $(
    pub fn $function_rust_name<F>(
    env: &napi::Env,
    handler: F,
    // TODO: generic errors
    ) -> Result<(), napi::Error>
    where
    F: for<'function_context> Fn(
    &'function_context napi::Env,
    $event_type,
    ) -> Result<(), napi::Error>
    + std::panic::RefUnwindSafe
    + 'static,
    {
    let vscode_object = super::VscodeContext::vscode(env)?;
    let event_container: bindgen_prelude::Object =
    vscode_object.get_named_property($namespace)?;
    crate::vscode_sys::macros::event_handler_body! {
    env,
    handler,
    event_container,
    $function_js_name,
    $function_rust_name($event_type)
    }
    }
    )*
    };
    }
    pub(crate) use namespace_event_handler;
  • replacement in extensions/vscode/src/vscode_sys/macros/mod.rs at line 11
    [2.77551][2.77551:77596]()
    pub(super) use event_handler::event_handler;
    [2.77551]
    [2.77596]
    pub(super) use event_handler::event_handler_body;
  • edit in extensions/vscode/src/vscode_sys/macros/mod.rs at line 13
    [2.77649]
    [2.77649]
    pub(super) use namespace::event_handler::namespace_event_handler;
  • edit in extensions/vscode/src/vscode_sys/macros/mod.rs at line 16
    [2.77769]
    [2.77769]
    pub(super) use object::event_handler::object_event_handler;
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 1
    [2.83905][2.83906:83935]()
    macro_rules! event_handler {
    [2.83905]
    [2.83935]
    macro_rules! event_handler_body {
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 3
    [2.83941][2.83941:84038]()
    $namespace:literal, $function_js_name:literal, $function_rust_name:ident($event_type:ty)
    [2.83941]
    [2.84038]
    $env:ident, $handler:ident, $event_container:expr, $function_js_name:literal, $function_rust_name:ident($event_type:ty)
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 5
    [2.84049][2.84049:84398](),[2.84398][3.1044:1088](),[3.1088][2.84398:84650](),[2.84398][2.84398:84650]()
    pub fn $function_rust_name<F>(
    env: &napi::Env,
    handler: F,
    // TODO: generic errors
    ) -> Result<(), napi::Error>
    where
    F: for<'function_context> Fn(
    &'function_context napi::Env,
    $event_type,
    ) -> Result<(), napi::Error>
    + std::panic::RefUnwindSafe
    + 'static,
    {
    let extension_context = super::VscodeContext::extension_context(env)?;
    let mut subscriptions: bindgen_prelude::Array =
    extension_context.get_named_property("subscriptions")?;
    [2.84049]
    [2.84650]
    let extension_context = crate::vscode_sys::VscodeContext::extension_context($env)?;
    let mut subscriptions: bindgen_prelude::Array =
    extension_context.get_named_property("subscriptions")?;
    let event_creator: bindgen_prelude::Function<
    bindgen_prelude::Function<$event_type, ()>,
    // TODO: disposable
    bindgen_prelude::Object,
    > = $event_container.get_named_property($function_js_name)?;
    let event_handler_fn: bindgen_prelude::Function<$event_type, ()> = $env
    .create_function_from_closure($function_js_name, move |function_context| {
    let parent_span = tracing::span!(tracing::Level::TRACE, "event_handler");
    let _entered_span = parent_span.enter();
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 19
    [2.84651][2.84651:85425]()
    let vscode_object = super::VscodeContext::vscode(env)?;
    let namespace: bindgen_prelude::Object =
    vscode_object.get_named_property($namespace)?;
    let event_creator: bindgen_prelude::Function<
    bindgen_prelude::Function<$event_type, ()>,
    // TODO: disposable
    bindgen_prelude::Object,
    > = namespace.get_named_property($function_js_name)?;
    let event_handler_fn: bindgen_prelude::Function<$event_type, ()> = env
    .create_function_from_closure($function_js_name, move |function_context| {
    let parent_span = tracing::span!(tracing::Level::TRACE, "event_handler");
    let _entered_span = parent_span.enter();
    [2.84651]
    [2.85425]
    let event = match function_context.args::<($event_type,)>() {
    Ok((event,)) => event,
    Err(error) => {
    tracing::error!(
    message = "Invalid arguments provided to event handler",
    event_handler = $function_js_name,
    ?error
    );
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 28
    [2.85426][2.85426:85555]()
    let event = match function_context.args::<($event_type,)>() {
    Ok((event,)) => event,
    [2.85426]
    [2.85555]
    return Err(napi::Error::from_reason(
    "Invalid arguments provided to event handler",
    ));
    }
    };
    match std::panic::catch_unwind(|| $handler(function_context.env, event)) {
    Ok(handler_result) => match handler_result {
    Ok(result) => Ok(result),
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 39
    [2.85640][3.1089:1178]()
    message = "Invalid arguments provided to event handler",
    [2.85640]
    [2.85703]
    message = "Event handler returned an error",
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 44
    [3.1180][3.1180:1356]()
    return Err(napi::Error::from_reason(
    "Invalid arguments provided to event handler",
    ));
    [3.1180]
    [2.85883]
    Err(napi::Error::from_reason("Event handler returned an error"))
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 46
    [2.85909][2.85909:85932]()
    };
    [2.85909]
    [2.85932]
    },
    Err(panic_payload) => {
    tracing::error!(
    message = "Event handler panicked",
    event_handler = $function_js_name,
    ?panic_payload
    );
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 54
    [2.85933][3.1357:1897](),[3.1897][2.86271:86272](),[2.86271][2.86271:86272](),[2.86272][3.1898:2469]()
    match std::panic::catch_unwind(|| handler(function_context.env, event)) {
    Ok(handler_result) => match handler_result {
    Ok(result) => Ok(result),
    Err(error) => {
    tracing::error!(
    message = "Event handler returned an error",
    event_handler = $function_js_name,
    ?error
    );
    Err(napi::Error::from_reason("Event handler returned an error"))
    }
    },
    Err(panic_payload) => {
    tracing::error!(
    message = "Event handler panicked",
    event_handler = $function_js_name,
    ?panic_payload
    );
    Err(napi::Error::from_reason("Event handler panicked"))
    }
    [2.85933]
    [3.2469]
    Err(napi::Error::from_reason("Event handler panicked"))
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 56
    [3.2491][2.86299:86320](),[2.86299][2.86299:86320]()
    })?;
    [3.2491]
    [2.86320]
    }
    })?;
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 59
    [2.86321][2.86321:86497]()
    let handler_subscription: bindgen_prelude::Object =
    event_creator.call(event_handler_fn)?;
    subscriptions.insert(handler_subscription)?;
    [2.86321]
    [2.86497]
    let handler_subscription: bindgen_prelude::Object = event_creator.call(event_handler_fn)?;
    subscriptions.insert(handler_subscription)?;
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 62
    [2.86498][2.86498:86527]()
    Ok(())
    }
    [2.86498]
    [2.86527]
    Ok(())
  • replacement in extensions/vscode/src/vscode_sys/macros/event_handler.rs at line 66
    [2.86537][2.86537:86567]()
    pub(crate) use event_handler;
    [2.86537]
    pub(crate) use event_handler_body;