Skip to main content

tsgo_client/
proto.rs

1use serde::{Deserialize, Deserializer};
2use serde_bytes::Bytes;
3#[derive(Debug, Clone, Deserialize)]
4#[non_exhaustive]
5pub struct ProjectResponse<'base> {
6    #[serde(borrow)]
7    pub root_files: Vec<&'base str>,
8    pub source_files: Vec<&'base Bytes>,
9    pub module_list: Vec<&'base str>,
10    #[serde(default)]
11    pub module_exports: Vec<Vec<u32>>,
12    pub semantic: Semantic,
13    pub diagnostics: Vec<Diagnostic>,
14    pub source_file_extra: Vec<SourceFileExtra>,
15}
16#[derive(Debug, Clone, Deserialize)]
17pub struct SourceFileExtra {
18    pub has_common_js_module_indicator: bool,
19    pub has_external_module_indicator: bool,
20}
21#[derive(Debug, Clone, Deserialize)]
22pub struct Location {
23    pub start: u32,
24    pub end: u32,
25}
26#[derive(Debug, Clone, Deserialize)]
27pub struct Diagnostic {
28    pub message: String,
29    pub category: u32,
30    pub file: u32,
31    pub loc: Location,
32}
33#[derive(Debug, Clone, Deserialize)]
34pub struct Semantic {
35    #[serde(deserialize_with = "vecmap")]
36    pub symtab: Vec<(u32, SymbolData)>,
37    #[serde(deserialize_with = "vecmap")]
38    pub typetab: Vec<(u32, TypeData)>,
39    #[serde(deserialize_with = "vecmap")]
40    pub sym2type: Vec<(u32, u32)>,
41    #[serde(deserialize_with = "vecmap")]
42    pub node2sym: Vec<(NodeReference, u32)>,
43    #[serde(deserialize_with = "vecmap")]
44    pub node2type: Vec<(NodeReference, u32)>,
45    #[serde(default, deserialize_with = "vecmap_or_empty")]
46    pub node_flags: Vec<(NodeReference, u32)>,
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    // Shorthand object binding symbols (local_symbol_id -> property_symbol_id).
55    #[serde(default, deserialize_with = "vecmap_or_empty")]
56    pub shorthand_binding_symbols: Vec<(u32, u32)>,
57    // Parameter property declarations create another symbol at the same name node; node2sym keeps the primary symbol.
58    #[serde(default, deserialize_with = "vecmap_or_empty")]
59    pub parameter_property_symbols: Vec<(NodeReference, u32)>,
60    // Globals and dependency exports qualified by namespace and name.
61    #[serde(default)]
62    pub external_symbols: Vec<ExternalSymbol>,
63}
64
65#[derive(Debug, Clone, Deserialize)]
66pub struct NodeReference {
67    pub sourcefile_id: u32,
68    pub start: u32,
69    pub end: u32,
70}
71
72#[derive(Debug, Clone, Deserialize)]
73pub struct SymbolData {
74    #[serde(with = "serde_bytes")]
75    pub name: Vec<u8>,
76    pub flags: u32,
77    pub check_flags: u32,
78    #[serde(default)]
79    pub decl: Option<NodeReference>,
80}
81
82#[derive(Debug, Clone, Deserialize)]
83pub struct ExternalSymbol {
84    pub symbol_id: u32,
85    #[serde(with = "serde_bytes")]
86    pub namespace: Vec<u8>,
87    #[serde(with = "serde_bytes")]
88    pub name: Vec<u8>,
89}
90
91#[derive(Debug, Clone, Deserialize)]
92pub struct TypeData {
93    pub id: u32,
94    pub flags: u32,
95    #[serde(default)]
96    pub object_flags: u32,
97    #[serde(default)]
98    pub symbol: Option<u32>,
99}
100
101#[derive(Debug, Clone, Deserialize)]
102pub struct PrimTypes {
103    pub string: u32,
104    pub number: u32,
105    pub any: u32,
106    pub error: u32,
107    pub unknown: u32,
108    pub never: u32,
109    pub undefined: u32,
110    pub null: u32,
111    pub void: u32,
112    pub bool: u32,
113}
114
115fn vecmap<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
116where
117    D: Deserializer<'de>,
118    K: Deserialize<'de>,
119    V: Deserialize<'de>,
120{
121    use serde::de::Visitor;
122    use std::marker::PhantomData;
123
124    struct VecMap<K, V>(PhantomData<(K, V)>);
125
126    impl<'de, K, V> Visitor<'de> for VecMap<K, V>
127    where
128        K: Deserialize<'de>,
129        V: Deserialize<'de>,
130    {
131        type Value = Vec<(K, V)>;
132
133        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
134            write!(formatter, "vec map")
135        }
136
137        fn visit_unit<E>(self) -> Result<Self::Value, E>
138        where
139            E: serde::de::Error,
140        {
141            Ok(Vec::new())
142        }
143
144        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
145        where
146            A: serde::de::MapAccess<'de>,
147        {
148            let len = map.size_hint().unwrap_or_default();
149            let len = std::cmp::min(len, 4096);
150            let mut out = Vec::with_capacity(len);
151
152            while let Some(e) = map.next_entry()? {
153                out.push(e);
154            }
155
156            Ok(out)
157        }
158    }
159
160    deserializer.deserialize_map(VecMap(PhantomData))
161}
162
163fn vecmap_or_empty<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
164where
165    D: Deserializer<'de>,
166    K: Deserialize<'de>,
167    V: Deserialize<'de>,
168{
169    use serde::de::Visitor;
170    use std::marker::PhantomData;
171
172    struct VecMapOrEmpty<K, V>(PhantomData<(K, V)>);
173
174    impl<'de, K, V> Visitor<'de> for VecMapOrEmpty<K, V>
175    where
176        K: Deserialize<'de>,
177        V: Deserialize<'de>,
178    {
179        type Value = Vec<(K, V)>;
180
181        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
182            write!(formatter, "vec map or nothing")
183        }
184
185        fn visit_unit<E>(self) -> Result<Self::Value, E>
186        where
187            E: serde::de::Error,
188        {
189            Ok(Vec::new())
190        }
191
192        fn visit_none<E>(self) -> Result<Self::Value, E>
193        where
194            E: serde::de::Error,
195        {
196            Ok(Vec::new())
197        }
198
199        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
200        where
201            A: serde::de::MapAccess<'de>,
202        {
203            let len = map.size_hint().unwrap_or_default();
204            let len = std::cmp::min(len, 4096);
205            let mut out = Vec::with_capacity(len);
206
207            while let Some(e) = map.next_entry()? {
208                out.push(e);
209            }
210
211            Ok(out)
212        }
213    }
214
215    deserializer.deserialize_any(VecMapOrEmpty(PhantomData))
216}
217
218impl Semantic {
219    /// Returns the value (local variable) symbol of an identifier in the shorthand property assignment.
220    ///
221    /// This is necessary as an identifier in shorthand property assignment contains two meanings:
222    /// property name and property value. For example, in `{ x }`, `x` is both the property name
223    /// and references the variable value.
224    ///
225    /// # Arguments
226    /// * `location` - The node reference to query
227    ///
228    /// # Returns
229    /// * `Some(u32)` - The symbol ID if found and has Value or Alias flags
230    /// * `None` - If no symbol is found or the symbol doesn't have the required flags
231    ///
232    /// # Reference
233    /// TypeScript implementation: https://github.com/microsoft/TypeScript/blob/9e8eaa1746b0d09c3cd29048126ef9cf24f29c03/src/compiler/checker.ts
234    pub fn get_shorthand_assignment_value_symbol(&self, location: &NodeReference) -> Option<u32> {
235        // Look up in the shorthand_symbols mapping
236        self.shorthand_symbols
237            .iter()
238            .find(|(node_ref, _)| {
239                node_ref.sourcefile_id == location.sourcefile_id
240                    && node_ref.start == location.start
241                    && node_ref.end == location.end
242            })
243            .map(|(_, sym_id)| *sym_id)
244    }
245
246    /// Returns the source property symbol of a shorthand object binding name.
247    ///
248    /// In `const { x } = value`, this maps the newly declared local `x` symbol
249    /// to the property symbol equivalent to `x` in `value.x`.
250    pub fn get_shorthand_binding_property_symbol(&self, local_symbol: u32) -> Option<u32> {
251        self.shorthand_binding_symbols
252            .iter()
253            .find(|(symbol, _)| *symbol == local_symbol)
254            .map(|(_, sym_id)| *sym_id)
255    }
256
257    /// Returns the extra symbol declared by a parameter property name.
258    ///
259    /// TypeScript parameter properties such as `constructor(private x: string)` declare two
260    /// symbols at the same source location. The primary symbol remains in `node2sym`; this
261    /// method returns the other one.
262    pub fn get_parameter_property_symbol(&self, location: &NodeReference) -> Option<u32> {
263        self.parameter_property_symbols
264            .iter()
265            .find(|(node_ref, _)| {
266                node_ref.sourcefile_id == location.sourcefile_id
267                    && node_ref.start == location.start
268                    && node_ref.end == location.end
269            })
270            .map(|(_, sym_id)| *sym_id)
271    }
272}