summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs')
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs121
1 files changed, 104 insertions, 17 deletions
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
index 4b01643c2..1d3e45aff 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
@@ -10,14 +10,15 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::ProcMacroKind;
-pub use crate::msg::flat::FlatTree;
+pub use crate::msg::flat::{FlatTree, TokenId};
// The versions of the server protocol
pub const NO_VERSION_CHECK_VERSION: u32 = 0;
pub const VERSION_CHECK_VERSION: u32 = 1;
pub const ENCODE_CLOSE_SPAN_VERSION: u32 = 2;
+pub const HAS_GLOBAL_SPANS: u32 = 3;
-pub const CURRENT_API_VERSION: u32 = ENCODE_CLOSE_SPAN_VERSION;
+pub const CURRENT_API_VERSION: u32 = HAS_GLOBAL_SPANS;
#[derive(Debug, Serialize, Deserialize)]
pub enum Request {
@@ -59,6 +60,26 @@ pub struct ExpandMacro {
pub env: Vec<(String, String)>,
pub current_dir: Option<String>,
+ /// marker for serde skip stuff
+ #[serde(skip_serializing_if = "ExpnGlobals::skip_serializing_if")]
+ #[serde(default)]
+ pub has_global_spans: ExpnGlobals,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct ExpnGlobals {
+ #[serde(skip_serializing)]
+ #[serde(default)]
+ pub serialize: bool,
+ pub def_site: usize,
+ pub call_site: usize,
+ pub mixed_site: usize,
+}
+
+impl ExpnGlobals {
+ fn skip_serializing_if(&self) -> bool {
+ !self.serialize
+ }
}
pub trait Message: Serialize + DeserializeOwned {
@@ -115,30 +136,89 @@ fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> {
#[cfg(test)]
mod tests {
+ use base_db::{
+ span::{ErasedFileAstId, SpanAnchor, SpanData, SyntaxContextId},
+ FileId,
+ };
+ use la_arena::RawIdx;
+ use text_size::{TextRange, TextSize};
+ use tt::{Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, Subtree, TokenTree};
+
use super::*;
- use crate::tt::*;
- fn fixture_token_tree() -> Subtree {
- let mut subtree = Subtree { delimiter: Delimiter::unspecified(), token_trees: Vec::new() };
- subtree
- .token_trees
- .push(TokenTree::Leaf(Ident { text: "struct".into(), span: TokenId(0) }.into()));
- subtree
- .token_trees
- .push(TokenTree::Leaf(Ident { text: "Foo".into(), span: TokenId(1) }.into()));
+ fn fixture_token_tree() -> Subtree<SpanData> {
+ let anchor = SpanAnchor {
+ file_id: FileId::from_raw(0),
+ ast_id: ErasedFileAstId::from_raw(RawIdx::from(0)),
+ };
+ let mut subtree = Subtree {
+ delimiter: Delimiter {
+ open: SpanData {
+ range: TextRange::empty(TextSize::new(0)),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
+ close: SpanData {
+ range: TextRange::empty(TextSize::new(13)),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
+ kind: DelimiterKind::Invisible,
+ },
+ token_trees: Vec::new(),
+ };
+ subtree.token_trees.push(TokenTree::Leaf(
+ Ident {
+ text: "struct".into(),
+ span: SpanData {
+ range: TextRange::at(TextSize::new(0), TextSize::of("struct")),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
+ }
+ .into(),
+ ));
+ subtree.token_trees.push(TokenTree::Leaf(
+ Ident {
+ text: "Foo".into(),
+ span: SpanData {
+ range: TextRange::at(TextSize::new(5), TextSize::of("Foo")),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
+ }
+ .into(),
+ ));
subtree.token_trees.push(TokenTree::Leaf(Leaf::Literal(Literal {
text: "Foo".into(),
- span: TokenId::unspecified(),
+
+ span: SpanData {
+ range: TextRange::at(TextSize::new(8), TextSize::of("Foo")),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
})));
subtree.token_trees.push(TokenTree::Leaf(Leaf::Punct(Punct {
char: '@',
- span: TokenId::unspecified(),
+ span: SpanData {
+ range: TextRange::at(TextSize::new(11), TextSize::of('@')),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
spacing: Spacing::Joint,
})));
subtree.token_trees.push(TokenTree::Subtree(Subtree {
delimiter: Delimiter {
- open: TokenId(2),
- close: TokenId::UNSPECIFIED,
+ open: SpanData {
+ range: TextRange::at(TextSize::new(12), TextSize::of('{')),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
+ close: SpanData {
+ range: TextRange::at(TextSize::new(13), TextSize::of('}')),
+ anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
kind: DelimiterKind::Brace,
},
token_trees: vec![],
@@ -149,19 +229,26 @@ mod tests {
#[test]
fn test_proc_macro_rpc_works() {
let tt = fixture_token_tree();
+ let mut span_data_table = Default::default();
let task = ExpandMacro {
- macro_body: FlatTree::new(&tt, CURRENT_API_VERSION),
+ macro_body: FlatTree::new(&tt, CURRENT_API_VERSION, &mut span_data_table),
macro_name: Default::default(),
attributes: None,
lib: std::env::current_dir().unwrap(),
env: Default::default(),
current_dir: Default::default(),
+ has_global_spans: ExpnGlobals {
+ serialize: true,
+ def_site: 0,
+ call_site: 0,
+ mixed_site: 0,
+ },
};
let json = serde_json::to_string(&task).unwrap();
// println!("{}", json);
let back: ExpandMacro = serde_json::from_str(&json).unwrap();
- assert_eq!(tt, back.macro_body.to_subtree(CURRENT_API_VERSION));
+ assert_eq!(tt, back.macro_body.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table));
}
}