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)]
25#[serde(rename_all = "camelCase")]
26pub struct Entry<'a> {
27    pub id: Id,
28    #[serde(flatten)]
29    pub data: Element<'a>,
30}
31
32#[derive(Debug, PartialEq, Serialize)]
33#[serde(rename_all = "camelCase")]
34#[serde(tag = "type")]
35#[allow(clippy::large_enum_variant)]
36pub enum Element<'a> {
37    Vertex(Vertex<'a>),
38    Edge(Edge),
39}
40
41#[derive(Debug, 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)]
136#[serde(rename_all = "camelCase")]
137#[serde(tag = "label")]
138pub enum Vertex<'a> {
139    MetaData(&'a MetaData),
140    /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
141    Project(Project),
142    Document(&'a 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
240#[derive(Debug, PartialEq, Serialize, Deserialize)]
241#[serde(rename_all = "camelCase")]
242pub struct EdgeData {
243    pub in_v: Id,
244    pub out_v: Id,
245}
246
247#[derive(Debug, PartialEq, Serialize, Deserialize)]
248#[serde(rename_all = "camelCase")]
249pub struct EdgeDataMultiIn {
250    pub in_vs: Vec<Id>,
251    pub out_v: Id,
252}
253
254#[derive(Debug, PartialEq, Serialize, Deserialize)]
255#[serde(untagged)]
256pub enum DefinitionResultType {
257    Scalar(LocationOrRangeId),
258    Array(LocationOrRangeId),
259}
260
261#[derive(Debug, PartialEq, Serialize, Deserialize)]
262#[serde(rename_all = "camelCase")]
263pub enum ItemKind {
264    Declarations,
265    Definitions,
266    References,
267    ReferenceResults,
268    ImplementationResults,
269}
270
271#[derive(Debug, PartialEq, Serialize, Deserialize)]
272#[serde(rename_all = "camelCase")]
273pub struct Item {
274    pub document: Id,
275    #[serde(skip_serializing_if = "Option::is_none")]
276    pub property: Option<ItemKind>,
277    #[serde(flatten)]
278    pub edge_data: EdgeDataMultiIn,
279}
280
281#[derive(Debug, PartialEq, Serialize, Deserialize)]
282#[serde(rename_all = "camelCase")]
283pub struct Document {
284    pub uri: Url,
285    pub language_id: EcoString,
286}
287
288/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
289#[derive(Debug, PartialEq, Serialize, Deserialize)]
290#[serde(rename_all = "camelCase")]
291pub struct ResultSet {
292    #[serde(skip_serializing_if = "Option::is_none")]
293    pub key: Option<String>,
294}
295
296/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
297#[derive(Debug, PartialEq, Serialize, Deserialize)]
298#[serde(rename_all = "camelCase")]
299pub struct Project {
300    #[serde(skip_serializing_if = "Option::is_none")]
301    pub resource: Option<Url>,
302    #[serde(skip_serializing_if = "Option::is_none")]
303    pub content: Option<String>,
304    pub kind: String,
305}
306
307#[derive(Debug, PartialEq, Serialize, Deserialize)]
308#[serde(rename_all = "camelCase")]
309pub struct MetaData {
310    /// The version of the LSIF format using semver notation. See <https://semver.org/>. Please note
311    /// the version numbers starting with 0 don't adhere to semver and adopters
312    /// have to assume that each new version is breaking.
313    pub version: String,
314
315    /// The project root (in form of an URI) used to compute this dump.
316    pub project_root: Url,
317
318    /// The string encoding used to compute line and character values in
319    /// positions and ranges.
320    pub position_encoding: Encoding,
321
322    /// Information about the tool that created the dump
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub tool_info: Option<ToolInfo>,
325}
326
327#[derive(Debug, PartialEq, Serialize, Deserialize)]
328#[serde(rename_all = "camelCase")]
329pub struct Repository {
330    pub r#type: String,
331    pub url: String,
332    #[serde(skip_serializing_if = "Option::is_none")]
333    pub commit_id: Option<String>,
334}
335
336#[derive(Debug, PartialEq, Serialize, Deserialize)]
337#[serde(rename_all = "camelCase")]
338pub struct PackageInformation {
339    pub name: String,
340    pub manager: String,
341    #[serde(skip_serializing_if = "Option::is_none")]
342    pub uri: Option<Url>,
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub content: Option<String>,
345    #[serde(skip_serializing_if = "Option::is_none")]
346    pub repository: Option<Repository>,
347    #[serde(skip_serializing_if = "Option::is_none")]
348    pub version: Option<String>,
349}