Skip to main content

oak_lsp/
types.rs

1use oak_core::{Arc, language::UniversalElementRole};
2use serde::{Deserialize, Serialize};
3
4pub use core::range::Range;
5pub use oak_folding::{FoldingRange, FoldingRangeKind};
6
7/// Represents a position in a source file (line and character).
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub struct Position {
10    /// Line number (0-indexed).
11    pub line: u32,
12    /// Character offset in the line (0-indexed).
13    pub character: u32,
14}
15
16/// Represents a range in a source file using line/character positions.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18pub struct LspRange {
19    /// The start position of the range.
20    pub start: Position,
21    /// The end position of the range.
22    pub end: Position,
23}
24
25/// Represents a location inside a resource.
26/// Can be either byte-based (Rust model) or line/column based (LSP model).
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
28#[serde(bound(serialize = "R: Serialize", deserialize = "R: Deserialize<'de>"))]
29pub struct Location<R = Range<usize>> {
30    /// The URI of the resource.
31    #[serde(with = "oak_core::serde_arc_str")]
32    pub uri: Arc<str>,
33    /// The range within the resource.
34    pub range: R,
35}
36
37/// A specialized location type for byte-based ranges.
38#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
39pub struct LocationRange {
40    /// The URI of the resource.
41    #[serde(with = "oak_core::serde_arc_str")]
42    pub uri: Arc<str>,
43    /// The byte range within the resource.
44    #[serde(with = "oak_core::serde_range")]
45    pub range: Range<usize>,
46}
47
48impl From<LocationRange> for Location<Range<usize>> {
49    fn from(loc: LocationRange) -> Self {
50        Self { uri: loc.uri, range: loc.range }
51    }
52}
53
54impl From<Location<Range<usize>>> for LocationRange {
55    fn from(loc: Location<Range<usize>>) -> Self {
56        Self { uri: loc.uri, range: loc.range }
57    }
58}
59
60impl From<oak_navigation::Location> for Location<Range<usize>> {
61    fn from(loc: oak_navigation::Location) -> Self {
62        Self { uri: loc.uri, range: loc.range }
63    }
64}
65
66impl From<oak_navigation::Location> for LocationRange {
67    fn from(loc: oak_navigation::Location) -> Self {
68        Self { uri: loc.uri, range: loc.range }
69    }
70}
71
72/// A source position with line, column, and offset.
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
74pub struct SourcePosition {
75    /// Line number (1-indexed).
76    pub line: u32,
77    /// Column number (1-indexed).
78    pub column: u32,
79    /// Byte offset (0-indexed).
80    pub offset: usize,
81    /// Length of the token/element.
82    pub length: usize,
83}
84
85/// A source location with an optional URL.
86#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
87pub struct SourceLocation {
88    /// Line number (1-indexed).
89    pub line: u32,
90    /// Column number (1-indexed).
91    pub column: u32,
92    /// Optional URL of the source file.
93    pub url: Option<url::Url>,
94}
95
96impl Default for SourceLocation {
97    fn default() -> Self {
98        Self { line: 1, column: 1, url: None }
99    }
100}
101
102/// A document highlight is a range inside a text document which deserves
103/// special attention. Usually a document highlight is visualized by changing
104/// the background color of its range.
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
106pub enum DocumentHighlightKind {
107    Text = 1,
108    Read = 2,
109    Write = 3,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
113pub struct DocumentHighlight {
114    pub range: LspRange,
115    pub kind: Option<DocumentHighlightKind>,
116}
117
118/// Represents a color in RGBA space.
119#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
120pub struct Color {
121    pub red: f32,
122    pub green: f32,
123    pub blue: f32,
124    pub alpha: f32,
125}
126
127/// Represents a color range from a document.
128#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
129pub struct ColorInformation {
130    pub range: LspRange,
131    pub color: Color,
132}
133
134/// Represents hover information.
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct Hover {
137    /// The hover's content as a markdown string.
138    pub contents: String,
139    /// An optional span to which this hover applies.
140    #[serde(with = "oak_core::serde_range::option")]
141    pub range: Option<Range<usize>>,
142}
143
144/// Represents an item in the document structure (e.g., in an outline or breadcrumbs).
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct StructureItem {
147    /// The name of this item (e.g., function name, class name).
148    pub name: String,
149    /// More detail about this item (e.g., function signature, type).
150    pub detail: Option<String>,
151    /// The universal role of this element.
152    pub role: UniversalElementRole,
153    /// The symbol kind.
154    pub kind: SymbolKind,
155    /// The range of the entire element in the source code.
156    #[serde(with = "oak_core::serde_range")]
157    pub range: Range<usize>,
158    /// The range that should be selected when clicking on this item.
159    /// Usually the range of the identifier.
160    #[serde(with = "oak_core::serde_range")]
161    pub selection_range: Range<usize>,
162    /// Whether this item is deprecated.
163    pub deprecated: bool,
164    /// Nested structure items (e.g., methods within a class).
165    pub children: Vec<StructureItem>,
166}
167
168/// Parameters for the `initialize` request.
169#[derive(Debug, Clone, Default, Serialize, Deserialize)]
170pub struct InitializeParams {
171    pub root_uri: Option<String>,
172    pub workspace_folders: Vec<WorkspaceFolder>,
173}
174
175/// A workspace folder.
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct WorkspaceFolder {
178    pub uri: String,
179    pub name: String,
180}
181
182/// Represents a symbol kind.
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
184pub enum SymbolKind {
185    File = 1,
186    Module = 2,
187    Namespace = 3,
188    Package = 4,
189    Class = 5,
190    Method = 6,
191    Property = 7,
192    Field = 8,
193    Constructor = 9,
194    Enum = 10,
195    Interface = 11,
196    Function = 12,
197    Variable = 13,
198    Constant = 14,
199    String = 15,
200    Number = 16,
201    Boolean = 17,
202    Array = 18,
203    Object = 19,
204    Key = 20,
205    Null = 21,
206    EnumMember = 22,
207    Struct = 23,
208    Event = 24,
209    Operator = 25,
210    TypeParameter = 26,
211}
212
213/// Represents a workspace symbol.
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct WorkspaceSymbol {
216    /// The name of the symbol.
217    pub name: String,
218    /// The kind of the symbol.
219    pub kind: SymbolKind,
220    /// The location of the symbol.
221    pub location: LocationRange,
222    /// The name of the container this symbol is in.
223    pub container_name: Option<String>,
224}
225
226/// Represents information about a symbol (e.g., function, variable, class).
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct SymbolInformation {
229    /// The name of the symbol.
230    pub name: String,
231    /// The kind of the symbol.
232    pub kind: SymbolKind,
233    /// The location of the symbol.
234    pub location: LocationRange,
235    /// The name of the container this symbol is in.
236    pub container_name: Option<String>,
237}
238
239/// Represents a change to the workspace.
240#[derive(Debug, Clone, Default, Serialize, Deserialize)]
241pub struct WorkspaceEdit {
242    /// The changes to the workspace.
243    pub changes: std::collections::HashMap<String, Vec<TextEdit>>,
244}
245
246/// Represents a text edit.
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct TextEdit {
249    /// The range of the text edit.
250    #[serde(with = "oak_core::serde_range")]
251    pub range: Range<usize>,
252    /// The new text.
253    pub new_text: String,
254}
255
256/// Represents a completion item.
257#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct CompletionItem {
259    /// The label of the completion item.
260    pub label: String,
261    /// The kind of the completion item.
262    pub kind: Option<CompletionItemKind>,
263    /// A human-readable string with additional information about this item.
264    pub detail: Option<String>,
265    /// A human-readable string that contains documentation about this item.
266    pub documentation: Option<String>,
267    /// The text that should be inserted when selecting this completion item.
268    pub insert_text: Option<String>,
269}
270
271/// Represents a completion item kind.
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
273pub enum CompletionItemKind {
274    Text = 1,
275    Method = 2,
276    Function = 3,
277    Constructor = 4,
278    Field = 5,
279    Variable = 6,
280    Class = 7,
281    Interface = 8,
282    Module = 9,
283    Property = 10,
284    Unit = 11,
285    Value = 12,
286    Enum = 13,
287    Keyword = 14,
288    Snippet = 15,
289    Color = 16,
290    File = 17,
291    Reference = 18,
292    Folder = 19,
293    EnumMember = 20,
294    Constant = 21,
295    Struct = 22,
296    Event = 23,
297    Operator = 24,
298    TypeParameter = 25,
299}
300
301/// Represents a diagnostic.
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct Diagnostic {
304    /// The range of the diagnostic.
305    #[serde(with = "oak_core::serde_range")]
306    pub range: Range<usize>,
307    /// The severity of the diagnostic.
308    pub severity: Option<DiagnosticSeverity>,
309    /// The diagnostic's code.
310    pub code: Option<String>,
311    /// The source of the diagnostic.
312    pub source: Option<String>,
313    /// The diagnostic's message.
314    pub message: String,
315}
316
317/// Represents a diagnostic severity.
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
319pub enum DiagnosticSeverity {
320    Error = 1,
321    Warning = 2,
322    Information = 3,
323    Hint = 4,
324}
325
326/// Represents a semantic token.
327#[derive(Debug, Clone, Serialize, Deserialize)]
328pub struct SemanticToken {
329    pub delta_line: u32,
330    pub delta_start: u32,
331    pub length: u32,
332    pub token_type: u32,
333    pub token_modifiers_bitset: u32,
334}
335
336/// Represents semantic tokens.
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct SemanticTokens {
339    pub result_id: Option<String>,
340    pub data: Vec<SemanticToken>,
341}
342
343/// Represents a selection range.
344#[derive(Debug, Clone, Serialize, Deserialize)]
345pub struct SelectionRange {
346    #[serde(with = "oak_core::serde_range")]
347    pub range: Range<usize>,
348    pub parent: Option<Box<SelectionRange>>,
349}
350
351/// Represents parameter information.
352#[derive(Debug, Clone, Serialize, Deserialize)]
353pub struct ParameterInformation {
354    pub label: String,
355    pub documentation: Option<String>,
356}
357
358/// Represents signature information.
359#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct SignatureInformation {
361    pub label: String,
362    pub documentation: Option<String>,
363    pub parameters: Option<Vec<ParameterInformation>>,
364    pub active_parameter: Option<u32>,
365}
366
367/// Represents signature help.
368#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct SignatureHelp {
370    pub signatures: Vec<SignatureInformation>,
371    pub active_signature: Option<u32>,
372    pub active_parameter: Option<u32>,
373}
374
375/// Represents an inlay hint.
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct InlayHint {
378    pub position: Position,
379    pub label: String,
380    pub kind: Option<InlayHintKind>,
381    pub tooltip: Option<String>,
382    pub padding_left: Option<bool>,
383    pub padding_right: Option<bool>,
384}
385
386/// Represents an inlay hint kind.
387#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
388pub enum InlayHintKind {
389    Type = 1,
390    Parameter = 2,
391}
392
393/// Represents a code action.
394#[derive(Debug, Clone, Serialize, Deserialize)]
395pub struct CodeAction {
396    pub title: String,
397    pub kind: Option<String>,
398    pub diagnostics: Option<Vec<Diagnostic>>,
399    pub edit: Option<WorkspaceEdit>,
400    pub command: Option<Command>,
401    pub is_preferred: Option<bool>,
402    pub disabled: Option<CodeActionDisabled>,
403}
404
405#[derive(Debug, Clone, Serialize, Deserialize)]
406pub struct CodeActionDisabled {
407    pub reason: String,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize)]
411pub struct Command {
412    pub title: String,
413    pub command: String,
414    pub arguments: Option<Vec<serde_json::Value>>,
415}
416
417impl From<UniversalElementRole> for SymbolKind {
418    fn from(role: UniversalElementRole) -> Self {
419        match role {
420            UniversalElementRole::Root => SymbolKind::File,
421            UniversalElementRole::Container => SymbolKind::Module,
422            UniversalElementRole::Definition => SymbolKind::Function,
423            UniversalElementRole::Binding => SymbolKind::Variable,
424            UniversalElementRole::Reference => SymbolKind::Variable,
425            UniversalElementRole::Typing => SymbolKind::Class,
426            UniversalElementRole::Statement => SymbolKind::Function,
427            UniversalElementRole::Expression => SymbolKind::Variable,
428            UniversalElementRole::Call => SymbolKind::Function,
429            UniversalElementRole::Metadata => SymbolKind::Property,
430            UniversalElementRole::Attribute => SymbolKind::Property,
431            UniversalElementRole::Documentation => SymbolKind::String,
432            UniversalElementRole::Value => SymbolKind::Constant,
433            UniversalElementRole::Error => SymbolKind::Null,
434            _ => SymbolKind::Function,
435        }
436    }
437}
438
439impl From<oak_symbols::SymbolInformation> for WorkspaceSymbol {
440    fn from(s: oak_symbols::SymbolInformation) -> Self {
441        Self { name: s.name, kind: SymbolKind::from(s.role), location: LocationRange { uri: s.uri, range: s.range }, container_name: s.container_name }
442    }
443}
444
445impl From<oak_symbols::SymbolInformation> for StructureItem {
446    fn from(s: oak_symbols::SymbolInformation) -> Self {
447        Self { name: s.name, detail: None, role: s.role, kind: SymbolKind::from(s.role), range: s.range.clone(), selection_range: s.range.clone(), deprecated: false, children: vec![] }
448    }
449}