1use serde::{Deserialize, Serialize};
2
3use crate::{
4 DocumentSelector, DynamicRegistrationClientCapabilities, Range, TextDocumentIdentifier,
5 TextDocumentPositionParams, WorkDoneProgressParams,
6};
7
8use std::collections::HashMap;
9
10pub type DocumentFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
11pub type DocumentRangeFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
12pub type DocumentOnTypeFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
13
14#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct DocumentOnTypeFormattingOptions {
18 pub first_trigger_character: String,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub more_trigger_character: Option<Vec<String>>,
24}
25
26#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
27#[serde(rename_all = "camelCase")]
28pub struct DocumentFormattingParams {
29 pub text_document: TextDocumentIdentifier,
31
32 pub options: FormattingOptions,
34
35 #[serde(flatten)]
36 pub work_done_progress_params: WorkDoneProgressParams,
37}
38
39#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct FormattingOptions {
43 pub tab_size: u32,
45
46 pub insert_spaces: bool,
48
49 #[serde(flatten)]
51 pub properties: HashMap<String, FormattingProperty>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub trim_trailing_whitespace: Option<bool>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub insert_final_newline: Option<bool>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub trim_final_newlines: Option<bool>,
64}
65
66#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
67#[serde(untagged)]
68pub enum FormattingProperty {
69 Bool(bool),
70 Number(i32),
71 String(String),
72}
73
74#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
75#[serde(rename_all = "camelCase")]
76pub struct DocumentRangeFormattingParams {
77 pub text_document: TextDocumentIdentifier,
79
80 pub range: Range,
82
83 pub options: FormattingOptions,
85
86 #[serde(flatten)]
87 pub work_done_progress_params: WorkDoneProgressParams,
88}
89
90#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
91#[serde(rename_all = "camelCase")]
92pub struct DocumentOnTypeFormattingParams {
93 #[serde(flatten)]
95 pub text_document_position: TextDocumentPositionParams,
96
97 pub ch: String,
99
100 pub options: FormattingOptions,
102}
103
104#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
106#[serde(rename_all = "camelCase")]
107pub struct DocumentOnTypeFormattingRegistrationOptions {
108 pub document_selector: Option<DocumentSelector>,
111
112 pub first_trigger_character: String,
114
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub more_trigger_character: Option<Vec<String>>,
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use crate::tests::test_serialization;
124
125 #[test]
126 fn formatting_options() {
127 test_serialization(
128 &FormattingOptions {
129 tab_size: 123,
130 insert_spaces: true,
131 properties: HashMap::new(),
132 trim_trailing_whitespace: None,
133 insert_final_newline: None,
134 trim_final_newlines: None,
135 },
136 r#"{"tabSize":123,"insertSpaces":true}"#,
137 );
138
139 test_serialization(
140 &FormattingOptions {
141 tab_size: 123,
142 insert_spaces: true,
143 properties: vec![("prop".to_string(), FormattingProperty::Number(1))]
144 .into_iter()
145 .collect(),
146 trim_trailing_whitespace: None,
147 insert_final_newline: None,
148 trim_final_newlines: None,
149 },
150 r#"{"tabSize":123,"insertSpaces":true,"prop":1}"#,
151 );
152 }
153}