diff --git a/crates/proc-macro-api/src/legacy_protocol/json.rs b/crates/proc-macro-api/src/legacy_protocol/json.rs index ec89f6a9e65d..8e50ed5a8589 100644 --- a/crates/proc-macro-api/src/legacy_protocol/json.rs +++ b/crates/proc-macro-api/src/legacy_protocol/json.rs @@ -1,6 +1,7 @@ //! Protocol functions for json. use std::io::{self, BufRead, Write}; +/// Reads a JSON message from the input stream. pub fn read_json<'a>( inp: &mut impl BufRead, buf: &'a mut String, @@ -26,6 +27,7 @@ pub fn read_json<'a>( } } +/// Writes a JSON message to the output stream. pub fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { tracing::debug!("> {}", msg); out.write_all(msg.as_bytes())?; diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs index 4b831e4acebb..968150c12b59 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -20,69 +20,103 @@ pub const VERSION_CHECK_VERSION: u32 = 1; pub const ENCODE_CLOSE_SPAN_VERSION: u32 = 2; pub const HAS_GLOBAL_SPANS: u32 = 3; pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4; -/// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field +/// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field. pub const EXTENDED_LEAF_DATA: u32 = 5; +/// Current API version of the proc-macro protocol. pub const CURRENT_API_VERSION: u32 = EXTENDED_LEAF_DATA; +/// Represents requests sent from the client to the proc-macro-srv. #[derive(Debug, Serialize, Deserialize)] pub enum Request { + /// Retrieves a list of macros from a given dynamic library. /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: Utf8PathBuf }, + + /// Expands a procedural macro. /// Since [`NO_VERSION_CHECK_VERSION`] ExpandMacro(Box), + + /// Performs an API version check between the client and the server. /// Since [`VERSION_CHECK_VERSION`] ApiVersionCheck {}, + + /// Sets server-specific configurations. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), } +/// Defines the mode used for handling span data. #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)] pub enum SpanMode { + /// Default mode, where spans are identified by an ID. #[default] Id, + + /// Rust Analyzer-specific span handling mode. RustAnalyzer, } +/// Represents responses sent from the proc-macro-srv to the client. #[derive(Debug, Serialize, Deserialize)] pub enum Response { + /// Returns a list of available macros in a dynamic library. /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros(Result, String>), + + /// Returns result of a macro expansion. /// Since [`NO_VERSION_CHECK_VERSION`] ExpandMacro(Result), + + /// Returns the API version supported by the server. /// Since [`NO_VERSION_CHECK_VERSION`] ApiVersionCheck(u32), + + /// Confirms the application of a configuration update. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), + + /// Returns the result of a macro expansion, including extended span data. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] ExpandMacroExtended(Result), } +/// Configuration settings for the proc-macro-srv. #[derive(Debug, Serialize, Deserialize, Default)] #[serde(default)] pub struct ServerConfig { + /// Defines how span data should be handled. pub span_mode: SpanMode, } +/// Represents an extended macro expansion response, including span data mappings. #[derive(Debug, Serialize, Deserialize)] pub struct ExpandMacroExtended { + /// The expanded syntax tree. pub tree: FlatTree, + /// Additional span data mappings. pub span_data_table: Vec, } +/// Represents an error message when a macro expansion results in a panic. #[derive(Debug, Serialize, Deserialize)] pub struct PanicMessage(pub String); +/// Represents a macro expansion request sent from the client. #[derive(Debug, Serialize, Deserialize)] pub struct ExpandMacro { + /// The path to the dynamic library containing the macro. pub lib: Utf8PathBuf, /// Environment variables to set during macro expansion. pub env: Vec<(String, String)>, + /// The current working directory for the macro expansion. pub current_dir: Option, + /// Macro expansion data, including the macro body, name and attributes. #[serde(flatten)] pub data: ExpandMacroData, } +/// Represents the input data required for expanding a macro. #[derive(Debug, Serialize, Deserialize)] pub struct ExpandMacroData { /// Argument of macro call. @@ -103,18 +137,24 @@ pub struct ExpandMacroData { #[serde(skip_serializing_if = "ExpnGlobals::skip_serializing_if")] #[serde(default)] pub has_global_spans: ExpnGlobals, + /// Table of additional span data. #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default)] pub span_data_table: Vec, } +/// Represents global expansion settings, including span resolution. #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)] pub struct ExpnGlobals { + /// Determines whether to serialize the expansion settings. #[serde(skip_serializing)] #[serde(default)] pub serialize: bool, + /// Defines the `def_site` span location. pub def_site: usize, + /// Defines the `call_site` span location. pub call_site: usize, + /// Defines the `mixed_site` span location. pub mixed_site: usize, } @@ -150,9 +190,11 @@ pub trait Message: serde::Serialize + DeserializeOwned { impl Message for Request {} impl Message for Response {} +/// Type alias for a function that reads protocol messages from a buffered input stream. #[allow(type_alias_bounds)] type ProtocolRead = for<'i, 'buf> fn(inp: &'i mut R, buf: &'buf mut String) -> io::Result>; +/// Type alias for a function that writes protocol messages to an output stream. #[allow(type_alias_bounds)] type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) -> io::Result<()>; diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs index dc3328ebcda4..7061f7ea474c 100644 --- a/crates/proc-macro-api/src/lib.rs +++ b/crates/proc-macro-api/src/lib.rs @@ -24,9 +24,12 @@ use crate::{ process::ProcMacroServerProcess, }; +/// Represents different kinds of procedural macros that can be expanded by the external server. #[derive(Copy, Clone, Eq, PartialEq, Debug, serde_derive::Serialize, serde_derive::Deserialize)] pub enum ProcMacroKind { + /// A macro that derives implementations for a struct or enum. CustomDerive, + /// An attribute-like procedural macro. Attr, // This used to be called FuncLike, so that's what the server expects currently. #[serde(alias = "Bang")] @@ -46,11 +49,13 @@ pub struct ProcMacroClient { path: AbsPathBuf, } +/// Represents a dynamically loaded library containing procedural macros. pub struct MacroDylib { path: AbsPathBuf, } impl MacroDylib { + /// Creates a new MacroDylib instance with the given path. pub fn new(path: AbsPathBuf) -> MacroDylib { MacroDylib { path } } @@ -78,6 +83,7 @@ impl PartialEq for ProcMacro { } } +/// Represents errors encountered when communicating with the proc-macro server. #[derive(Clone, Debug)] pub struct ServerError { pub message: String, @@ -106,6 +112,7 @@ impl ProcMacroClient { Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() }) } + /// Returns the absolute path to the proc-macro server. pub fn server_path(&self) -> &AbsPath { &self.path } @@ -130,20 +137,25 @@ impl ProcMacroClient { } } + /// Checks if the proc-macro server has exited. pub fn exited(&self) -> Option<&ServerError> { self.process.exited() } } impl ProcMacro { + /// Returns the name of the procedural macro. pub fn name(&self) -> &str { &self.name } + /// Returns the type of procedural macro. pub fn kind(&self) -> ProcMacroKind { self.kind } + /// Expands the procedural macro by sending an expansion request to the server. + /// This includes span information and environmental context. pub fn expand( &self, subtree: tt::SubtreeView<'_, Span>, diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs index d998b23d3bbe..d8ae2df7faa9 100644 --- a/crates/proc-macro-api/src/process.rs +++ b/crates/proc-macro-api/src/process.rs @@ -21,6 +21,7 @@ use crate::{ ProcMacroKind, ServerError, }; +/// Represents a process handling proc-macro communication. #[derive(Debug)] pub(crate) struct ProcMacroServerProcess { /// The state of the proc-macro server process, the protocol is currently strictly sequential @@ -32,6 +33,7 @@ pub(crate) struct ProcMacroServerProcess { exited: OnceLock>, } +/// Maintains the state of the proc-macro server process. #[derive(Debug)] struct ProcessSrvState { process: Process, @@ -40,6 +42,7 @@ struct ProcessSrvState { } impl ProcMacroServerProcess { + /// Starts the proc-macro server and performs a version check pub(crate) fn run( process_path: &AbsPath, env: impl IntoIterator, impl AsRef)> @@ -85,14 +88,17 @@ impl ProcMacroServerProcess { } } + /// Returns the server error if the process has exited. pub(crate) fn exited(&self) -> Option<&ServerError> { self.exited.get().map(|it| &it.0) } + /// Retrieves the API version of the proc-macro server. pub(crate) fn version(&self) -> u32 { self.version } + /// Checks the API version of the running proc-macro server. fn version_check(&self) -> Result { let request = Request::ApiVersionCheck {}; let response = self.send_task(request)?; @@ -103,6 +109,7 @@ impl ProcMacroServerProcess { } } + /// Enable support for rust-analyzer span mode if the server supports it. fn enable_rust_analyzer_spans(&self) -> Result { let request = Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer }); let response = self.send_task(request)?; @@ -113,6 +120,7 @@ impl ProcMacroServerProcess { } } + /// Finds proc-macros in a given dynamic library. pub(crate) fn find_proc_macros( &self, dylib_path: &AbsPath, @@ -127,6 +135,7 @@ impl ProcMacroServerProcess { } } + /// Sends a request to the proc-macro server and waits for a response. pub(crate) fn send_task(&self, req: Request) -> Result { if let Some(server_error) = self.exited.get() { return Err(server_error.0.clone()); @@ -177,12 +186,14 @@ impl ProcMacroServerProcess { } } +/// Manages the execution of the proc-macro server process. #[derive(Debug)] struct Process { child: JodChild, } impl Process { + /// Runs a new proc-macro server process with the specified environment variables. fn run( path: &AbsPath, env: impl IntoIterator, impl AsRef)>, @@ -191,6 +202,7 @@ impl Process { Ok(Process { child }) } + /// Retrieves stdin and stdout handles for the process. fn stdio(&mut self) -> Option<(ChildStdin, BufReader)> { let stdin = self.child.stdin.take()?; let stdout = self.child.stdout.take()?; @@ -200,6 +212,7 @@ impl Process { } } +/// Creates and configures a new child process for the proc-macro server. fn mk_child( path: &AbsPath, env: impl IntoIterator, impl AsRef)>, @@ -221,6 +234,7 @@ fn mk_child( cmd.spawn() } +/// Sends a request to the server and reads the response. fn send_request( mut writer: &mut impl Write, mut reader: &mut impl BufRead,