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/// Format document on type options
15#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct DocumentOnTypeFormattingOptions {
18 /// A character on which formatting should be triggered, like `}`.
19 pub first_trigger_character: String,
20
21 /// More trigger characters.
22 #[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 /// The document to format.
30 pub text_document: TextDocumentIdentifier,
31
32 /// The format options.
33 pub options: FormattingOptions,
34
35 #[serde(flatten)]
36 pub work_done_progress_params: WorkDoneProgressParams,
37}
38
39/// Value-object describing what options formatting should use.
40#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct FormattingOptions {
43 /// Size of a tab in spaces.
44 pub tab_size: u32,
45
46 /// Prefer spaces over tabs.
47 pub insert_spaces: bool,
48
49 /// Signature for further properties.
50 #[serde(flatten)]
51 pub properties: HashMap<String, FormattingProperty>,
52
53 /// Trim trailing whitespace on a line.
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub trim_trailing_whitespace: Option<bool>,
56
57 /// Insert a newline character at the end of the file if one does not exist.
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub insert_final_newline: Option<bool>,
60
61 /// Trim all newlines after the final newline at the end of the file.
62 #[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 /// The document to format.
78 pub text_document: TextDocumentIdentifier,
79
80 /// The range to format
81 pub range: Range,
82
83 /// The format options
84 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 /// Text Document and Position fields.
94 #[serde(flatten)]
95 pub text_document_position: TextDocumentPositionParams,
96
97 /// The character that has been typed.
98 pub ch: String,
99
100 /// The format options.
101 pub options: FormattingOptions,
102}
103
104/// Extends TextDocumentRegistrationOptions
105#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
106#[serde(rename_all = "camelCase")]
107pub struct DocumentOnTypeFormattingRegistrationOptions {
108 /// A document selector to identify the scope of the registration. If set to null
109 /// the document selector provided on the client side will be used.
110 pub document_selector: Option<DocumentSelector>,
111
112 /// A character on which formatting should be triggered, like `}`.
113 pub first_trigger_character: String,
114
115 /// More trigger characters.
116 #[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}
154