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