tinymist_query/index/
protocol.rs

1//! Borrowed from `lsp-types` crate and modified to fit our need.
2//! Types of Language Server Index Format (LSIF). LSIF is a standard format
3//! for language servers or other programming tools to dump their knowledge
4//! about a workspace.
5//!
6//! Based on <https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/>
7
8#![allow(missing_docs)]
9// todo: large_enum_variant
10
11use ecow::EcoString;
12use lsp_types::{Range, SemanticTokens, Url};
13use serde::{Deserialize, Serialize};
14
15pub type Id = i32;
16
17#[derive(Debug, PartialEq, Serialize, Deserialize)]
18#[serde(untagged)]
19pub enum LocationOrRangeId {
20    Location(lsp_types::Location),
21    RangeId(Id),
22}
23
24#[derive(Debug, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct Entry {
27    pub id: Id,
28    #[serde(flatten)]
29    pub data: Element,
30}
31
32#[derive(Debug, PartialEq, Serialize, Deserialize)]
33#[serde(rename_all = "camelCase")]
34#[serde(tag = "type")]
35#[allow(clippy::large_enum_variant)]
36pub enum Element {
37    Vertex(Vertex),
38    Edge(Edge),
39}
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub struct ToolInfo {
43    pub name: String,
44    #[serde(default = "Default::default")]
45    #[serde(skip_serializing_if = "Vec::is_empty")]
46    pub args: Vec<String>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub version: Option<String>,
49}
50
51#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
52pub enum Encoding {
53    /// Currently only 'utf-16' is supported due to the limitations in LSP.
54    #[serde(rename = "utf-16")]
55    Utf16,
56}
57
58#[derive(Debug, PartialEq, Serialize, Deserialize)]
59pub struct RangeBasedDocumentSymbol {
60    pub id: Id,
61    #[serde(default = "Default::default")]
62    #[serde(skip_serializing_if = "Vec::is_empty")]
63    pub children: Vec<RangeBasedDocumentSymbol>,
64}
65
66#[derive(Debug, PartialEq, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68#[serde(untagged)]
69pub enum DocumentSymbolOrRangeBasedVec {
70    DocumentSymbol(Vec<lsp_types::DocumentSymbol>),
71    RangeBased(Vec<RangeBasedDocumentSymbol>),
72}
73
74#[derive(Debug, PartialEq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct DefinitionTag {
77    /// The text covered by the range     
78    text: String,
79    /// The symbol kind.
80    kind: lsp_types::SymbolKind,
81    /// Indicates if this symbol is deprecated.
82    #[serde(default)]
83    #[serde(skip_serializing_if = "std::ops::Not::not")]
84    deprecated: bool,
85    /// The full range of the definition not including leading/trailing
86    /// whitespace but everything else, e.g comments and code.
87    /// The range must be included in fullRange.
88    full_range: Range,
89    /// Optional detail information for the definition.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    detail: Option<String>,
92}
93
94#[derive(Debug, PartialEq, Serialize, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub struct DeclarationTag {
97    /// The text covered by the range     
98    text: String,
99    /// The symbol kind.
100    kind: lsp_types::SymbolKind,
101    /// Indicates if this symbol is deprecated.
102    #[serde(default)]
103    deprecated: bool,
104    /// The full range of the definition not including leading/trailing
105    /// whitespace but everything else, e.g comments and code.
106    /// The range must be included in fullRange.
107    full_range: Range,
108    /// Optional detail information for the definition.
109    #[serde(skip_serializing_if = "Option::is_none")]
110    detail: Option<String>,
111}
112
113#[derive(Debug, PartialEq, Serialize, Deserialize)]
114#[serde(rename_all = "camelCase")]
115pub struct ReferenceTag {
116    text: String,
117}
118
119#[derive(Debug, PartialEq, Serialize, Deserialize)]
120#[serde(rename_all = "camelCase")]
121pub struct UnknownTag {
122    text: String,
123}
124
125#[derive(Debug, PartialEq, Serialize, Deserialize)]
126#[serde(rename_all = "camelCase")]
127#[serde(tag = "type")]
128pub enum RangeTag {
129    Definition(DefinitionTag),
130    Declaration(DeclarationTag),
131    Reference(ReferenceTag),
132    Unknown(UnknownTag),
133}
134
135#[derive(Debug, PartialEq, Serialize, Deserialize)]
136#[serde(rename_all = "camelCase")]
137#[serde(tag = "label")]
138pub enum Vertex {
139    MetaData(MetaData),
140    /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
141    Project(Project),
142    Document(Document),
143    /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#ranges>
144    Range {
145        #[serde(flatten)]
146        range: Range,
147        #[serde(skip_serializing_if = "Option::is_none")]
148        tag: Option<RangeTag>,
149    },
150    /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
151    ResultSet(ResultSet),
152    Moniker(lsp_types::Moniker),
153    PackageInformation(PackageInformation),
154
155    #[serde(rename = "$event")]
156    Event(Event),
157
158    DefinitionResult,
159    DeclarationResult,
160    TypeDefinitionResult,
161    ReferenceResult,
162    ImplementationResult,
163    FoldingRangeResult {
164        result: Vec<lsp_types::FoldingRange>,
165    },
166    SemanticTokensResult {
167        result: SemanticTokens,
168    },
169    HoverResult {
170        result: lsp_types::Hover,
171    },
172    DocumentSymbolResult {
173        result: DocumentSymbolOrRangeBasedVec,
174    },
175    DocumentLinkResult {
176        result: Vec<lsp_types::DocumentLink>,
177    },
178    DiagnosticResult {
179        result: Vec<lsp_types::Diagnostic>,
180    },
181}
182
183#[derive(Debug, PartialEq, Serialize, Deserialize)]
184#[serde(rename_all = "camelCase")]
185pub enum EventKind {
186    Begin,
187    End,
188}
189
190#[derive(Debug, PartialEq, Serialize, Deserialize)]
191#[serde(rename_all = "camelCase")]
192pub enum EventScope {
193    Document,
194    Project,
195}
196
197#[derive(Debug, PartialEq, Serialize, Deserialize)]
198pub struct Event {
199    pub kind: EventKind,
200    pub scope: EventScope,
201    pub data: Id,
202}
203
204#[derive(Debug, PartialEq, Serialize, Deserialize)]
205#[serde(rename_all = "camelCase")]
206#[serde(tag = "label")]
207pub enum Edge {
208    Contains(EdgeDataMultiIn),
209    Moniker(EdgeData),
210    NextMoniker(EdgeData),
211    Next(EdgeData),
212    PackageInformation(EdgeData),
213    Item(Item),
214
215    // Methods
216    #[serde(rename = "textDocument/definition")]
217    Definition(EdgeData),
218    #[serde(rename = "textDocument/declaration")]
219    Declaration(EdgeData),
220    #[serde(rename = "textDocument/hover")]
221    Hover(EdgeData),
222    #[serde(rename = "textDocument/references")]
223    References(EdgeData),
224    #[serde(rename = "textDocument/implementation")]
225    Implementation(EdgeData),
226    #[serde(rename = "textDocument/typeDefinition")]
227    TypeDefinition(EdgeData),
228    #[serde(rename = "textDocument/foldingRange")]
229    FoldingRange(EdgeData),
230    #[serde(rename = "textDocument/documentLink")]
231    DocumentLink(EdgeData),
232    #[serde(rename = "textDocument/documentSymbol")]
233    DocumentSymbol(EdgeData),
234    #[serde(rename = "textDocument/diagnostic")]
235    Diagnostic(EdgeData),
236    #[serde(rename = "textDocument/semanticTokens")]
237    SemanticTokens(EdgeData),
238}
239
240impl Edge {
241    pub fn out_v(&self) -> Id {
242        match self {
243            Edge::Contains(data) => data.out_v,
244            Edge::Item(item) => item.edge_data.out_v,
245            Edge::Moniker(data)
246            | Edge::NextMoniker(data)
247            | Edge::Next(data)
248            | Edge::PackageInformation(data)
249            | Edge::Definition(data)
250            | Edge::Declaration(data)
251            | Edge::Hover(data)
252            | Edge::References(data)
253            | Edge::Implementation(data)
254            | Edge::TypeDefinition(data)
255            | Edge::FoldingRange(data)
256            | Edge::DocumentLink(data)
257            | Edge::DocumentSymbol(data)
258            | Edge::Diagnostic(data)
259            | Edge::SemanticTokens(data) => data.out_v,
260        }
261    }
262}
263
264#[derive(Debug, PartialEq, Serialize, Deserialize)]
265#[serde(rename_all = "camelCase")]
266pub struct EdgeData {
267    pub in_v: Id,
268    pub out_v: Id,
269}
270
271#[derive(Debug, PartialEq, Serialize, Deserialize)]
272#[serde(rename_all = "camelCase")]
273pub struct EdgeDataMultiIn {
274    pub in_vs: Vec<Id>,
275    pub out_v: Id,
276}
277
278#[derive(Debug, PartialEq, Serialize, Deserialize)]
279#[serde(untagged)]
280pub enum DefinitionResultType {
281    Scalar(LocationOrRangeId),
282    Array(LocationOrRangeId),
283}
284
285#[derive(Debug, PartialEq, Serialize, Deserialize)]
286#[serde(rename_all = "camelCase")]
287pub enum ItemKind {
288    Declarations,
289    Definitions,
290    References,
291    ReferenceResults,
292    ImplementationResults,
293}
294
295#[derive(Debug, PartialEq, Serialize, Deserialize)]
296#[serde(rename_all = "camelCase")]
297pub struct Item {
298    pub document: Id,
299    #[serde(skip_serializing_if = "Option::is_none")]
300    pub property: Option<ItemKind>,
301    #[serde(flatten)]
302    pub edge_data: EdgeDataMultiIn,
303}
304
305#[derive(Debug, PartialEq, Serialize, Deserialize)]
306#[serde(rename_all = "camelCase")]
307pub struct Document {
308    pub uri: Url,
309    pub language_id: EcoString,
310}
311
312/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
313#[derive(Debug, PartialEq, Serialize, Deserialize)]
314#[serde(rename_all = "camelCase")]
315pub struct ResultSet {
316    #[serde(skip_serializing_if = "Option::is_none")]
317    pub key: Option<String>,
318}
319
320/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
321#[derive(Debug, PartialEq, Serialize, Deserialize)]
322#[serde(rename_all = "camelCase")]
323pub struct Project {
324    #[serde(skip_serializing_if = "Option::is_none")]
325    pub resource: Option<Url>,
326    #[serde(skip_serializing_if = "Option::is_none")]
327    pub content: Option<String>,
328    pub kind: String,
329}
330
331#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
332#[serde(rename_all = "camelCase")]
333pub struct MetaData {
334    /// The version of the LSIF format using semver notation. See <https://semver.org/>. Please note
335    /// the version numbers starting with 0 don't adhere to semver and adopters
336    /// have to assume that each new version is breaking.
337    pub version: String,
338
339    /// The project root (in form of an URI) used to compute this dump.
340    pub project_root: Url,
341
342    /// The string encoding used to compute line and character values in
343    /// positions and ranges.
344    pub position_encoding: Encoding,
345
346    /// Information about the tool that created the dump
347    #[serde(skip_serializing_if = "Option::is_none")]
348    pub tool_info: Option<ToolInfo>,
349}
350
351#[derive(Debug, PartialEq, Serialize, Deserialize)]
352#[serde(rename_all = "camelCase")]
353pub struct Repository {
354    pub r#type: String,
355    pub url: String,
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub commit_id: Option<String>,
358}
359
360#[derive(Debug, PartialEq, Serialize, Deserialize)]
361#[serde(rename_all = "camelCase")]
362pub struct PackageInformation {
363    pub name: String,
364    pub manager: String,
365    #[serde(skip_serializing_if = "Option::is_none")]
366    pub uri: Option<Url>,
367    #[serde(skip_serializing_if = "Option::is_none")]
368    pub content: Option<String>,
369    #[serde(skip_serializing_if = "Option::is_none")]
370    pub repository: Option<Repository>,
371    #[serde(skip_serializing_if = "Option::is_none")]
372    pub version: Option<String>,
373}