Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-api/src/legacy_protocol/msg.rs')
| -rw-r--r-- | crates/proc-macro-api/src/legacy_protocol/msg.rs | 203 |
1 files changed, 156 insertions, 47 deletions
diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs index b0e80dedcd..a6e228d977 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -13,20 +13,23 @@ use crate::{ProcMacroKind, codec::Codec}; /// Represents requests sent from the client to the proc-macro-srv. #[derive(Debug, Serialize, Deserialize)] pub enum Request { + // IMPORTANT: Keep his first, otherwise postcard will break as its not a self describing format + // As such, this is the only request that needs to be supported across all protocol versions + // and by keeping it first, we ensure it always has the same discriminant encoding in postcard + /// Performs an API version check between the client and the server. + /// Since [`crate::version::VERSION_CHECK_VERSION`] + ApiVersionCheck {}, + /// Retrieves a list of macros from a given dynamic library. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: Utf8PathBuf }, /// Expands a procedural macro. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ExpandMacro(Box<ExpandMacro>), - /// 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`] + /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), } @@ -44,24 +47,27 @@ pub enum SpanMode { /// Represents responses sent from the proc-macro-srv to the client. #[derive(Debug, Serialize, Deserialize)] pub enum Response { + // IMPORTANT: Keep his first, otherwise postcard will break as its not a self describing format + // As such, this is the only request that needs to be supported across all protocol versions + // and by keeping it first, we ensure it always has the same discriminant encoding in postcard + /// Returns the API version supported by the server. + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] + ApiVersionCheck(u32), + /// Returns a list of available macros in a dynamic library. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ListMacros(Result<Vec<(String, ProcMacroKind)>, String>), /// Returns result of a macro expansion. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ExpandMacro(Result<FlatTree, PanicMessage>), - /// 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`] + /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), /// Returns the result of a macro expansion, including extended span data. - /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] + /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`] ExpandMacroExtended(Result<ExpandMacroExtended, PanicMessage>), } @@ -179,7 +185,7 @@ mod tests { use super::*; - fn fixture_token_tree() -> TopSubtree<Span> { + fn fixture_token_tree_top_many_none() -> TopSubtree<Span> { let anchor = SpanAnchor { file_id: span::EditionedFileId::new( span::FileId::from_raw(0xe4e4e), @@ -195,7 +201,7 @@ mod tests { ctx: SyntaxContext::root(Edition::CURRENT), }, close: Span { - range: TextRange::empty(TextSize::new(19)), + range: TextRange::empty(TextSize::new(0)), anchor, ctx: SyntaxContext::root(Edition::CURRENT), }, @@ -253,10 +259,18 @@ mod tests { ctx: SyntaxContext::root(Edition::CURRENT), }, ); + builder.open( + DelimiterKind::Bracket, + Span { + range: TextRange::at(TextSize::new(15), TextSize::of('[')), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + ); builder.push(Leaf::Literal(Literal { symbol: sym::INTEGER_0, span: Span { - range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), + range: TextRange::at(TextSize::new(16), TextSize::of("0u32")), anchor, ctx: SyntaxContext::root(Edition::CURRENT), }, @@ -264,45 +278,140 @@ mod tests { suffix: Some(sym::u32), })); builder.close(Span { - range: TextRange::at(TextSize::new(19), TextSize::of('}')), + range: TextRange::at(TextSize::new(20), TextSize::of(']')), anchor, ctx: SyntaxContext::root(Edition::CURRENT), }); + builder.close(Span { + range: TextRange::at(TextSize::new(21), TextSize::of('}')), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }); + + builder.build() + } + + fn fixture_token_tree_top_empty_none() -> TopSubtree<Span> { + let anchor = SpanAnchor { + file_id: span::EditionedFileId::new( + span::FileId::from_raw(0xe4e4e), + span::Edition::CURRENT, + ), + ast_id: ROOT_ERASED_FILE_AST_ID, + }; + + let builder = TopSubtreeBuilder::new(Delimiter { + open: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + close: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + kind: DelimiterKind::Invisible, + }); + + builder.build() + } + + fn fixture_token_tree_top_empty_brace() -> TopSubtree<Span> { + let anchor = SpanAnchor { + file_id: span::EditionedFileId::new( + span::FileId::from_raw(0xe4e4e), + span::Edition::CURRENT, + ), + ast_id: ROOT_ERASED_FILE_AST_ID, + }; + + let builder = TopSubtreeBuilder::new(Delimiter { + open: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + close: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + kind: DelimiterKind::Brace, + }); + builder.build() } #[test] fn test_proc_macro_rpc_works() { - let tt = fixture_token_tree(); - for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION { - let mut span_data_table = Default::default(); - let task = ExpandMacro { - data: ExpandMacroData { - macro_body: FlatTree::from_subtree(tt.view(), v, &mut span_data_table), - macro_name: Default::default(), - attributes: None, - has_global_spans: ExpnGlobals { - serialize: true, - def_site: 0, - call_site: 0, - mixed_site: 0, + for tt in [ + fixture_token_tree_top_many_none, + fixture_token_tree_top_empty_none, + fixture_token_tree_top_empty_brace, + ] { + for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION { + let tt = tt(); + let mut span_data_table = Default::default(); + let task = ExpandMacro { + data: ExpandMacroData { + macro_body: FlatTree::from_subtree(tt.view(), v, &mut span_data_table), + macro_name: Default::default(), + attributes: None, + has_global_spans: ExpnGlobals { + serialize: true, + def_site: 0, + call_site: 0, + mixed_site: 0, + }, + span_data_table: Vec::new(), }, - span_data_table: Vec::new(), - }, - lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(), - env: Default::default(), - current_dir: Default::default(), - }; - - let json = serde_json::to_string(&task).unwrap(); - // println!("{}", json); - let back: ExpandMacro = serde_json::from_str(&json).unwrap(); - - assert!( - tt == back.data.macro_body.to_subtree_resolved(v, &span_data_table), - "version: {v}" - ); + lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(), + env: Default::default(), + current_dir: Default::default(), + }; + + let json = serde_json::to_string(&task).unwrap(); + // println!("{}", json); + let back: ExpandMacro = serde_json::from_str(&json).unwrap(); + + assert_eq!( + tt, + back.data.macro_body.to_subtree_resolved(v, &span_data_table), + "version: {v}" + ); + } + } + } + + #[test] + #[cfg(feature = "sysroot-abi")] + fn test_proc_macro_rpc_works_ts() { + for tt in [ + fixture_token_tree_top_many_none, + fixture_token_tree_top_empty_none, + fixture_token_tree_top_empty_brace, + ] { + let tt = tt(); + for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION { + let mut span_data_table = Default::default(); + let flat_tree = FlatTree::from_subtree(tt.view(), v, &mut span_data_table); + assert_eq!( + tt, + flat_tree.clone().to_subtree_resolved(v, &span_data_table), + "version: {v}" + ); + let ts = flat_tree.to_tokenstream_resolved(v, &span_data_table, |a, b| a.cover(b)); + let call_site = *span_data_table.first().unwrap(); + let mut span_data_table = Default::default(); + assert_eq!( + tt, + FlatTree::from_tokenstream(ts.clone(), v, call_site, &mut span_data_table) + .to_subtree_resolved(v, &span_data_table), + "version: {v}, ts:\n{ts:#?}" + ); + } } } } |