1
1
use crate :: edit:: { Replacement , ToRangeExt } ;
2
+ use crate :: fix:: Fixes ;
2
3
use crate :: server:: api:: LSPResult ;
3
4
use crate :: server:: { client:: Notifier , Result } ;
4
5
use crate :: session:: DocumentSnapshot ;
6
+ use crate :: { PositionEncoding , TextDocument } ;
5
7
use lsp_types:: { self as types, request as req} ;
8
+ use ruff_python_ast:: PySourceType ;
6
9
use ruff_source_file:: LineIndex ;
10
+ use ruff_workspace:: FormatterSettings ;
7
11
use types:: TextEdit ;
8
12
9
13
pub ( crate ) struct Format ;
@@ -23,25 +27,73 @@ impl super::BackgroundDocumentRequestHandler for Format {
23
27
}
24
28
}
25
29
30
+ /// Formats either a full text document or each individual cell in a single notebook document.
31
+ pub ( super ) fn format_full_document ( snapshot : & DocumentSnapshot ) -> Result < Fixes > {
32
+ let mut fixes = Fixes :: default ( ) ;
33
+
34
+ if let Some ( notebook) = snapshot. query ( ) . as_notebook ( ) {
35
+ for ( url, text_document) in notebook
36
+ . urls ( )
37
+ . map ( |url| ( url. clone ( ) , notebook. cell_document_by_uri ( url) . unwrap ( ) ) )
38
+ {
39
+ if let Some ( changes) = format_text_document (
40
+ text_document,
41
+ snapshot. query ( ) . source_type ( ) ,
42
+ snapshot. query ( ) . settings ( ) . formatter ( ) ,
43
+ snapshot. encoding ( ) ,
44
+ true ,
45
+ ) ? {
46
+ fixes. insert ( url, changes) ;
47
+ }
48
+ }
49
+ } else {
50
+ if let Some ( changes) = format_text_document (
51
+ snapshot. query ( ) . as_single_document ( ) . unwrap ( ) ,
52
+ snapshot. query ( ) . source_type ( ) ,
53
+ snapshot. query ( ) . settings ( ) . formatter ( ) ,
54
+ snapshot. encoding ( ) ,
55
+ false ,
56
+ ) ? {
57
+ fixes. insert ( snapshot. query ( ) . make_key ( ) . into_url ( ) , changes) ;
58
+ }
59
+ }
60
+
61
+ Ok ( fixes)
62
+ }
63
+
64
+ /// Formats either a full text document or an specific notebook cell. If the query within the snapshot is a notebook document
65
+ /// with no selected cell, this will throw an error.
26
66
pub ( super ) fn format_document ( snapshot : & DocumentSnapshot ) -> Result < super :: FormatResponse > {
27
- let doc = snapshot
67
+ let text_document = snapshot
28
68
. query ( )
29
69
. as_single_document ( )
30
70
. expect ( "format should only be called on text documents or notebook cells" ) ;
31
- let source = doc. contents ( ) ;
32
- let mut formatted = crate :: format:: format (
33
- doc,
71
+ format_text_document (
72
+ text_document,
34
73
snapshot. query ( ) . source_type ( ) ,
35
74
snapshot. query ( ) . settings ( ) . formatter ( ) ,
75
+ snapshot. encoding ( ) ,
76
+ snapshot. query ( ) . as_notebook ( ) . is_some ( ) ,
36
77
)
37
- . with_failure_code ( lsp_server:: ErrorCode :: InternalError ) ?;
78
+ }
79
+
80
+ fn format_text_document (
81
+ text_document : & TextDocument ,
82
+ source_type : PySourceType ,
83
+ formatter_settings : & FormatterSettings ,
84
+ encoding : PositionEncoding ,
85
+ is_notebook : bool ,
86
+ ) -> Result < super :: FormatResponse > {
87
+ let source = text_document. contents ( ) ;
88
+ let mut formatted = crate :: format:: format ( text_document, source_type, formatter_settings)
89
+ . with_failure_code ( lsp_server:: ErrorCode :: InternalError ) ?;
38
90
// fast path - if the code is the same, return early
39
91
if formatted == source {
40
92
return Ok ( None ) ;
41
93
}
42
94
43
95
// special case - avoid adding a newline to a notebook cell if it didn't already exist
44
- if snapshot . query ( ) . as_notebook ( ) . is_some ( ) {
96
+ if is_notebook {
45
97
let mut trimmed = formatted. as_str ( ) ;
46
98
if !source. ends_with ( "\r \n " ) {
47
99
trimmed = trimmed. trim_end_matches ( "\r \n " ) ;
@@ -57,7 +109,7 @@ pub(super) fn format_document(snapshot: &DocumentSnapshot) -> Result<super::Form
57
109
58
110
let formatted_index: LineIndex = LineIndex :: from_source_text ( & formatted) ;
59
111
60
- let unformatted_index = doc . index ( ) ;
112
+ let unformatted_index = text_document . index ( ) ;
61
113
62
114
let Replacement {
63
115
source_range,
@@ -70,7 +122,7 @@ pub(super) fn format_document(snapshot: &DocumentSnapshot) -> Result<super::Form
70
122
) ;
71
123
72
124
Ok ( Some ( vec ! [ TextEdit {
73
- range: source_range. to_range( source, unformatted_index, snapshot . encoding( ) ) ,
125
+ range: source_range. to_range( source, unformatted_index, encoding) ,
74
126
new_text: formatted[ formatted_range] . to_owned( ) ,
75
127
} ] ) )
76
128
}
0 commit comments