diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index fce206830297baf1c256a7c87c86b2564529149b..5f3eb2caaffa9c055c8f038197beb41b0d105b73 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -524,6 +524,8 @@ impl LanguageServer { ServerCapabilities { document_highlight_provider: Some(OneOf::Left(true)), code_action_provider: Some(CodeActionProviderCapability::Simple(true)), + document_formatting_provider: Some(OneOf::Left(true)), + document_range_formatting_provider: Some(OneOf::Left(true)), ..Default::default() } } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a89317db90410d99c9d876b9206adace06ec8682..53ca4bf3329c0ee8263499a54663558cb5ee95bc 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1314,15 +1314,47 @@ impl Project { } for (buffer, buffer_abs_path, lang_server) in local_buffers { - let lsp_edits = lang_server - .request::(lsp::DocumentFormattingParams { - text_document: lsp::TextDocumentIdentifier::new( - lsp::Url::from_file_path(&buffer_abs_path).unwrap(), - ), - options: Default::default(), - work_done_progress_params: Default::default(), - }) - .await?; + let capabilities = if let Some(capabilities) = lang_server.capabilities().await { + capabilities + } else { + continue; + }; + + let text_document = lsp::TextDocumentIdentifier::new( + lsp::Url::from_file_path(&buffer_abs_path).unwrap(), + ); + let lsp_edits = if capabilities + .document_formatting_provider + .map_or(false, |provider| provider != lsp::OneOf::Left(false)) + { + lang_server + .request::(lsp::DocumentFormattingParams { + text_document, + options: Default::default(), + work_done_progress_params: Default::default(), + }) + .await? + } else if capabilities + .document_range_formatting_provider + .map_or(false, |provider| provider != lsp::OneOf::Left(false)) + { + let buffer_start = lsp::Position::new(0, 0); + let buffer_end = buffer + .read_with(&cx, |buffer, _| buffer.max_point_utf16()) + .to_lsp_position(); + lang_server + .request::( + lsp::DocumentRangeFormattingParams { + text_document, + range: lsp::Range::new(buffer_start, buffer_end), + options: Default::default(), + work_done_progress_params: Default::default(), + }, + ) + .await? + } else { + continue; + }; if let Some(lsp_edits) = lsp_edits { let edits = buffer diff --git a/crates/text/src/rope.rs b/crates/text/src/rope.rs index 3d1cb28eb18bc0605a64cc40aa66b4618a2dcb2b..ce666968b2146f8a956029b139593fd4e0c1b2b9 100644 --- a/crates/text/src/rope.rs +++ b/crates/text/src/rope.rs @@ -126,6 +126,10 @@ impl Rope { self.chunks.extent(&()) } + pub fn max_point_utf16(&self) -> PointUtf16 { + self.chunks.extent(&()) + } + pub fn cursor(&self, offset: usize) -> Cursor { Cursor::new(self, offset) } diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 95441a12080c148afa07cfe0527b8db20b38ec06..89943777e06e4d21ef488a215c807064319e71a0 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1526,6 +1526,10 @@ impl BufferSnapshot { self.visible_text.max_point() } + pub fn max_point_utf16(&self) -> PointUtf16 { + self.visible_text.max_point_utf16() + } + pub fn point_to_offset(&self, point: Point) -> usize { self.visible_text.point_to_offset(point) }