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}
70
71#[derive(Debug, Clone, Deserialize)]
72pub struct TypeData {
73    pub id: u32,
74    pub flags: u32,
75}
76
77#[derive(Debug, Clone, Deserialize)]
78pub struct PrimTypes {
79    pub string: u32,
80    pub number: u32,
81    pub any: u32,
82    pub error: u32,
83    pub unknown: u32,
84    pub never: u32,
85    pub undefined: u32,
86    pub null: u32,
87    pub void: u32,
88    pub bool: u32,
89}
90
91#[derive(Debug, Clone, Deserialize)]
92pub struct TypeExtra {
93    pub name: HashMap<TypeId, serde_bytes::ByteBuf>,
94    pub func: HashMap<TypeId, FunctionData>,
95}
96#[derive(Debug, Clone, Deserialize)]
97pub struct FunctionData {
98    pub signatures: Vec<Signature>,
99}
100#[derive(Debug, Clone, Deserialize)]
101pub struct Signature {
102    pub result: TypeId,
103}
104
105fn vecmap<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
106where
107    D: Deserializer<'de>,
108    K: Deserialize<'de>,
109    V: Deserialize<'de>,
110{
111    use serde::de::Visitor;
112    use std::marker::PhantomData;
113
114    struct VecMap<K, V>(PhantomData<(K, V)>);
115
116    impl<'de, K, V> Visitor<'de> for VecMap<K, V>
117    where
118        K: Deserialize<'de>,
119        V: Deserialize<'de>,
120    {
121        type Value = Vec<(K, V)>;
122
123        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
124            write!(formatter, "vec map")
125        }
126
127        fn visit_unit<E>(self) -> Result<Self::Value, E>
128        where
129            E: serde::de::Error,
130        {
131            Ok(Vec::new())
132        }
133
134        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
135        where
136            A: serde::de::MapAccess<'de>,
137        {
138            let len = map.size_hint().unwrap_or_default();
139            let len = std::cmp::min(len, 4096);
140            let mut out = Vec::with_capacity(len);
141
142            while let Some(e) = map.next_entry()? {
143                out.push(e);
144            }
145
146            Ok(out)
147        }
148    }
149
150    deserializer.deserialize_map(VecMap(PhantomData))
151}
152
153fn vecmap_or_empty<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
154where
155    D: Deserializer<'de>,
156    K: Deserialize<'de>,
157    V: Deserialize<'de>,
158{
159    use serde::de::Visitor;
160    use std::marker::PhantomData;
161
162    struct VecMapOrEmpty<K, V>(PhantomData<(K, V)>);
163
164    impl<'de, K, V> Visitor<'de> for VecMapOrEmpty<K, V>
165    where
166        K: Deserialize<'de>,
167        V: Deserialize<'de>,
168    {
169        type Value = Vec<(K, V)>;
170
171        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
172            write!(formatter, "vec map or nothing")
173        }
174
175        fn visit_unit<E>(self) -> Result<Self::Value, E>
176        where
177            E: serde::de::Error,
178        {
179            Ok(Vec::new())
180        }
181
182        fn visit_none<E>(self) -> Result<Self::Value, E>
183        where
184            E: serde::de::Error,
185        {
186            Ok(Vec::new())
187        }
188
189        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
190        where
191            A: serde::de::MapAccess<'de>,
192        {
193            let len = map.size_hint().unwrap_or_default();
194            let len = std::cmp::min(len, 4096);
195            let mut out = Vec::with_capacity(len);
196
197            while let Some(e) = map.next_entry()? {
198                out.push(e);
199            }
200
201            Ok(out)
202        }
203    }
204
205    deserializer.deserialize_any(VecMapOrEmpty(PhantomData))
206}
207
208impl Semantic {
209    /// Returns the value (local variable) symbol of an identifier in the shorthand property assignment.
210    ///
211    /// This is necessary as an identifier in shorthand property assignment contains two meanings:
212    /// property name and property value. For example, in `{ x }`, `x` is both the property name
213    /// and references the variable value.
214    ///
215    /// # Arguments
216    /// * `location` - The node reference to query
217    ///
218    /// # Returns
219    /// * `Some(u32)` - The symbol ID if found and has Value or Alias flags
220    /// * `None` - If no symbol is found or the symbol doesn't have the required flags
221    ///
222    /// # Reference
223    /// TypeScript implementation: https://github.com/microsoft/TypeScript/blob/9e8eaa1746b0d09c3cd29048126ef9cf24f29c03/src/compiler/checker.ts
224    pub fn get_shorthand_assignment_value_symbol(&self, location: &NodeReference) -> Option<u32> {
225        // Look up in the shorthand_symbols mapping
226        self.shorthand_symbols
227            .iter()
228            .find(|(node_ref, _)| {
229                node_ref.sourcefile_id == location.sourcefile_id
230                    && node_ref.start == location.start
231                    && node_ref.end == location.end
232            })
233            .map(|(_, sym_id)| *sym_id)
234    }
235}