Skip to main content

tamasfe_lsp_types/
formatting.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    DocumentSelector, Range, TextDocumentIdentifier, TextDocumentPositionParams,
5    WorkDoneProgressParams,
6};
7
8use std::collections::HashMap;
9
10/// Format document on type options
11#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub struct DocumentOnTypeFormattingOptions {
14    /// A character on which formatting should be triggered, like `}`.
15    pub first_trigger_character: String,
16
17    /// More trigger characters.
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub more_trigger_character: Option<Vec<String>>,
20}
21
22#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
23#[serde(rename_all = "camelCase")]
24pub struct DocumentFormattingParams {
25    /// The document to format.
26    pub text_document: TextDocumentIdentifier,
27
28    /// The format options.
29    pub options: FormattingOptions,
30
31    #[serde(flatten)]
32    pub work_done_progress_params: WorkDoneProgressParams,
33}
34
35/// Value-object describing what options formatting should use.
36#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
37#[serde(rename_all = "camelCase")]
38pub struct FormattingOptions {
39    /// Size of a tab in spaces.
40    pub tab_size: u32,
41
42    /// Prefer spaces over tabs.
43    pub insert_spaces: bool,
44
45    /// Signature for further properties.
46    #[serde(flatten)]
47    pub properties: HashMap<String, FormattingProperty>,
48
49    /// Trim trailing whitespaces on a line.
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub trim_trailing_whitespace: Option<bool>,
52
53    /// Insert a newline character at the end of the file if one does not exist.
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub insert_final_newline: Option<bool>,
56
57    /// Trim all newlines after the final newline at the end of the file.
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub trim_final_newlines: Option<bool>,
60}
61
62#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
63#[serde(untagged)]
64pub enum FormattingProperty {
65    Bool(bool),
66    Number(i32),
67    String(String),
68}
69
70#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
71#[serde(rename_all = "camelCase")]
72pub struct DocumentRangeFormattingParams {
73    /// The document to format.
74    pub text_document: TextDocumentIdentifier,
75
76    /// The range to format
77    pub range: Range,
78
79    /// The format options
80    pub options: FormattingOptions,
81
82    #[serde(flatten)]
83    pub work_done_progress_params: WorkDoneProgressParams,
84}
85
86#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
87#[serde(rename_all = "camelCase")]
88pub struct DocumentOnTypeFormattingParams {
89    /// Text Document and Position fields.
90    #[serde(flatten)]
91    pub text_document_position: TextDocumentPositionParams,
92
93    /// The character that has been typed.
94    pub ch: String,
95
96    /// The format options.
97    pub options: FormattingOptions,
98}
99
100/// Extends TextDocumentRegistrationOptions
101#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
102#[serde(rename_all = "camelCase")]
103pub struct DocumentOnTypeFormattingRegistrationOptions {
104    /// A document selector to identify the scope of the registration. If set to null
105    /// the document selector provided on the client side will be used.
106    pub document_selector: Option<DocumentSelector>,
107
108    /// A character on which formatting should be triggered, like `}`.
109    pub first_trigger_character: String,
110
111    /// More trigger characters.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub more_trigger_character: Option<Vec<String>>,
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119    use crate::tests::test_serialization;
120
121    #[test]
122    fn formatting_options() {
123        test_serialization(
124            &FormattingOptions {
125                tab_size: 123,
126                insert_spaces: true,
127                properties: HashMap::new(),
128                trim_trailing_whitespace: None,
129                insert_final_newline: None,
130                trim_final_newlines: None,
131            },
132            r#"{"tabSize":123,"insertSpaces":true}"#,
133        );
134
135        test_serialization(
136            &FormattingOptions {
137                tab_size: 123,
138                insert_spaces: true,
139                properties: vec![("prop".to_string(), FormattingProperty::Number(1))]
140                    .into_iter()
141                    .collect(),
142                trim_trailing_whitespace: None,
143                insert_final_newline: None,
144                trim_final_newlines: None,
145            },
146            r#"{"tabSize":123,"insertSpaces":true,"prop":1}"#,
147        );
148    }
149}