Skip to main content

tsgo_client/
proto.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Deserializer};
4use serde_bytes::Bytes;
5type TypeId = u32;
6#[derive(Debug, Clone, Deserialize)]
7#[non_exhaustive]
8pub struct ProjectResponse<'base> {
9    #[serde(borrow)]
10    pub root_files: Vec<&'base str>,
11    pub source_files: Vec<&'base Bytes>,
12    pub module_list: Vec<&'base str>,
13    pub semantic: Semantic,
14    pub diagnostics: Vec<Diagnostic>,
15    pub source_file_extra: Vec<SourceFileExtra>,
16}
17#[derive(Debug, Clone, Deserialize)]
18pub struct SourceFileExtra {
19    pub has_common_js_module_indicator: bool,
20    pub has_external_module_indicator: bool,
21}
22#[derive(Debug, Clone, Deserialize)]
23pub struct Location {
24    pub start: u32,
25    pub end: u32,
26}
27#[derive(Debug, Clone, Deserialize)]
28pub struct Diagnostic {
29    pub message: String,
30    pub category: u32,
31    pub file: u32,
32    pub loc: Location,
33}
34#[derive(Debug, Clone, Deserialize)]
35pub struct Semantic {
36    #[serde(deserialize_with = "vecmap")]
37    pub symtab: Vec<(u32, SymbolData)>,
38    #[serde(deserialize_with = "vecmap")]
39    pub typetab: Vec<(u32, TypeData)>,
40    #[serde(deserialize_with = "vecmap")]
41    pub sym2type: Vec<(u32, u32)>,
42    #[serde(deserialize_with = "vecmap")]
43    pub node2sym: Vec<(NodeReference, u32)>,
44    #[serde(deserialize_with = "vecmap")]
45    pub node2type: Vec<(NodeReference, u32)>,
46    pub type_extra: TypeExtra,
47    pub primtypes: PrimTypes,
48    // (aliasSymbolId, targetSymbolId)
49    #[serde(default, deserialize_with = "vecmap_or_empty")]
50    pub alias_symbols: Vec<(u32, u32)>,
51    // Shorthand property assignment value symbols (node -> value_symbol_id)
52    #[serde(default, deserialize_with = "vecmap_or_empty")]
53    pub shorthand_symbols: Vec<(NodeReference, u32)>,
54}
55
56#[derive(Debug, Clone, Deserialize)]
57pub struct NodeReference {
58    pub sourcefile_id: u32,
59    pub start: u32,
60    pub end: u32,
61}
62
63#[derive(Debug, Clone, Deserialize)]
64pub struct SymbolData {
65    #[serde(with = "serde_bytes")]
66    pub name: Vec<u8>,
67    pub flags: u32,
68    pub check_flags: u32,
69    #[serde(default)]
70    pub decl: Option<NodeReference>,
71}
72
73#[derive(Debug, Clone, Deserialize)]
74pub struct TypeData {
75    pub id: u32,
76    pub flags: u32,
77}
78
79#[derive(Debug, Clone, Deserialize)]
80pub struct PrimTypes {
81    pub string: u32,
82    pub number: u32,
83    pub any: u32,
84    pub error: u32,
85    pub unknown: u32,
86    pub never: u32,
87    pub undefined: u32,
88    pub null: u32,
89    pub void: u32,
90    pub bool: u32,
91}
92
93#[derive(Debug, Clone, Deserialize)]
94pub struct TypeExtra {
95    pub name: HashMap<TypeId, serde_bytes::ByteBuf>,
96    pub func: HashMap<TypeId, FunctionData>,
97}
98#[derive(Debug, Clone, Deserialize)]
99pub struct FunctionData {
100    pub signatures: Vec<Signature>,
101}
102#[derive(Debug, Clone, Deserialize)]
103pub struct Signature {
104    pub result: TypeId,
105}
106
107fn vecmap<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
108where
109    D: Deserializer<'de>,
110    K: Deserialize<'de>,
111    V: Deserialize<'de>,
112{
113    use serde::de::Visitor;
114    use std::marker::PhantomData;
115
116    struct VecMap<K, V>(PhantomData<(K, V)>);
117
118    impl<'de, K, V> Visitor<'de> for VecMap<K, V>
119    where
120        K: Deserialize<'de>,
121        V: Deserialize<'de>,
122    {
123        type Value = Vec<(K, V)>;
124
125        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
126            write!(formatter, "vec map")
127        }
128
129        fn visit_unit<E>(self) -> Result<Self::Value, E>
130        where
131            E: serde::de::Error,
132        {
133            Ok(Vec::new())
134        }
135
136        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
137        where
138            A: serde::de::MapAccess<'de>,
139        {
140            let len = map.size_hint().unwrap_or_default();
141            let len = std::cmp::min(len, 4096);
142            let mut out = Vec::with_capacity(len);
143
144            while let Some(e) = map.next_entry()? {
145                out.push(e);
146            }
147
148            Ok(out)
149        }
150    }
151
152    deserializer.deserialize_map(VecMap(PhantomData))
153}
154
155fn vecmap_or_empty<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
156where
157    D: Deserializer<'de>,
158    K: Deserialize<'de>,
159    V: Deserialize<'de>,
160{
161    use serde::de::Visitor;
162    use std::marker::PhantomData;
163
164    struct VecMapOrEmpty<K, V>(PhantomData<(K, V)>);
165
166    impl<'de, K, V> Visitor<'de> for VecMapOrEmpty<K, V>
167    where
168        K: Deserialize<'de>,
169        V: Deserialize<'de>,
170    {
171        type Value = Vec<(K, V)>;
172
173        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
174            write!(formatter, "vec map or nothing")
175        }
176
177        fn visit_unit<E>(self) -> Result<Self::Value, E>
178        where
179            E: serde::de::Error,
180        {
181            Ok(Vec::new())
182        }
183
184        fn visit_none<E>(self) -> Result<Self::Value, E>
185        where
186            E: serde::de::Error,
187        {
188            Ok(Vec::new())
189        }
190
191        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
192        where
193            A: serde::de::MapAccess<'de>,
194        {
195            let len = map.size_hint().unwrap_or_default();
196            let len = std::cmp::min(len, 4096);
197            let mut out = Vec::with_capacity(len);
198
199            while let Some(e) = map.next_entry()? {
200                out.push(e);
201            }
202
203            Ok(out)
204        }
205    }
206
207    deserializer.deserialize_any(VecMapOrEmpty(PhantomData))
208}
209
210impl Semantic {
211    /// Returns the value (local variable) symbol of an identifier in the shorthand property assignment.
212    ///
213    /// This is necessary as an identifier in shorthand property assignment contains two meanings:
214    /// property name and property value. For example, in `{ x }`, `x` is both the property name
215    /// and references the variable value.
216    ///
217    /// # Arguments
218    /// * `location` - The node reference to query
219    ///
220    /// # Returns
221    /// * `Some(u32)` - The symbol ID if found and has Value or Alias flags
222    /// * `None` - If no symbol is found or the symbol doesn't have the required flags
223    ///
224    /// # Reference
225    /// TypeScript implementation: https://github.com/microsoft/TypeScript/blob/9e8eaa1746b0d09c3cd29048126ef9cf24f29c03/src/compiler/checker.ts
226    pub fn get_shorthand_assignment_value_symbol(&self, location: &NodeReference) -> Option<u32> {
227        // Look up in the shorthand_symbols mapping
228        self.shorthand_symbols
229            .iter()
230            .find(|(node_ref, _)| {
231                node_ref.sourcefile_id == location.sourcefile_id
232                    && node_ref.start == location.start
233                    && node_ref.end == location.end
234            })
235            .map(|(_, sym_id)| *sym_id)
236    }
237}